Go的当前运行时设计假定程序员负责检测何时终止goroutine和何时终止程序。程序员需要计算goroutine以及整个程序的终止条件。可以通过调用
os.Exit或从
main()函数返回以常规方式终止程序。
main()通过立即在所述通道上接收来创建通道并延迟退出,是一种防止
main退出的有效方法。但是它不能解决检测何时终止程序的问题。
如果在
main()函数进入等待所有goroutines终止循环之前无法计算goroutine的数量,则需要发送增量,以便
main函数可以跟踪正在运行的goroutine的数量:
// Receives the change in the number of goroutinesvar goroutineDelta = make(chan int)func main() { go forever() numGoroutines := 0 for diff := range goroutineDelta { numGoroutines += diff if numGoroutines == 0 { os.Exit(0) } }}// Conceptual prefunc forever() { for { if needToCreateANewGoroutine { // Make sure to do this before "go f()", not within f() goroutineDelta <- +1 go f() } }}func f() { // When the termination condition for this goroutine is detected, do: goroutineDelta <- -1}另一种方法是将频道替换为
sync.WaitGroup。这种方法的缺点是
wg.Add(int)需要在调用之前先进行调用
wg.Wait(),因此必须在其中至少创建一个goroutine,
main()然后才能在程序的任何部分中创建后续goroutine:
var wg sync.WaitGroupfunc main() { // Create at least 1 goroutine wg.Add(1) go f() go forever() wg.Wait()}// Conceptual prefunc forever() { for { if needToCreateANewGoroutine { wg.Add(1) go f() } }}func f() { // When the termination condition for this goroutine is detected, do: wg.Done()}


