如何优雅的退出goroutine

问题来源
项目中,同步数据的时候使用多个goroutine来对一组数据进行同步请求,同步采用http的方式,所有的数据同步完成需要一个整体的响应时间,在响应时间内goroutine按照正常的结果来处理,如果超过了响应时间那么对于还没有处理完的goroutine则认为是数据同步异常。
golang中判断超时的处理办法
在golang中通过channel来对程序的超时进行判断。

  • main方法通过select的方式来接收c1中的信息。如果select接收到了time.After发来的结果,那么判断程序运行的具体内容已经超过1s,则goruntine超时。
//举个例子 func main(){ c1 := make(chan string, 1) defer close(c1) go func(){ //需要运行的具体内容 c1 <- "result" }() select { case res := <-c1: fmt.Println(res) case <-time.After(time.Second * 1): fmt.Println("timeout 1") } }

  • 这里的超时判断使用了channel,context包也是通过chanel来对超时进行通知,不过有更丰富的操作。
  • 但是注意到,虽然main方法得到了goruntine超时的信息,但是goruntine并没有停止。如果阻塞的goruntine没有得到及时的处理,那么goruntine会越来越多。需要一种方式来让goruntine停下来。
  • 值得注意的一点:goruntine的退出是不会随着调用其的方法退出的,但如果主程序退出了,那么goruntine一定会退出
优雅的退出goruntine
【如何优雅的退出goroutine】最开始的想法是,通过在外部停止的方法来停掉所有超时的goruntine。
  • 对于golang,这种方法是其不推荐的,同时也是很危险的。关于goid的内容how to get goid这里有解释
  • 优雅的退出goruntine的方法是,严格的掌握控制每一个goruntine的运行时间(对于向上透明的方法,更应该了解其超时机制来避免运行超时的产生)。对于遇到的http这种同步这种问题,则需要对请求超时进行设置。
  • 当你开始一个goruntine的时候,一定要知道goruntine会在何时停止。
一些相关的参考:
针对“从外部结束一个 goroutine”的分析
end a blocked goroutine from outside
in golang, does it make sense to write non-blocking code?
What happens when a goroutine blocks
why 1000 goroutine generats 1000 os threads
知乎goruntine介绍

    推荐阅读