等待 goroutines
当 main
函数结束时 ,程序结束 ,因此通常的做法是等待所有 goroutine 完成。一个常见的解决方案是使用 sync.WaitGroup对象。
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup // 1
func routine(i int) {
defer wg.Done() // 3
fmt.Printf("routine %v finished\n", i)
}
func main() {
wg.Add(10) // 2
for i := 0; i < 10; i++ {
go routine(i) // *
}
wg.Wait() // 4
fmt.Println("main finished")
}
WaitGroup 按执行顺序使用:
- 全局变量声明。使其全局化是使其对所有函数和方法可见的最简单方法。
- 增加柜台。这必须在主 goroutine 中完成,因为由于内存模型保证, 无法保证新启动的 goroutine 将在 4 之前执行。
- 减少柜台。这必须在 goroutine 的出口处完成。通过使用延迟调用,我们确保无论函数如何结束 ,都会在函数结束时调用它。
- 等待计数器达到 0.这必须在主 goroutine 中完成,以防止程序在所有 goroutine 完成之前退出。
* 在开始新的 goroutine 之前评估参数。因此,有必要在 wg.Add(10)
之前明确定义它们的值,以便可能恐慌的代码不会增加计数器。向 WaitGroup 添加 10 个项目,因此它将等待 10 个项目,然后 wg.Wait
将控制权返回给 main()
goroutine。这里,i 的值在 for 循环中定义。