author: ningan123
date: 2023-03-21 11:05
updated: 2023-03-21 11:09
说明
官方文档对 WaitGroup 的描述是:一个 WaitGroup 对象可以等待一组协程结束
。使用方法是:
- main 协程通过调用
wg.Add(delta int)
设置 worker 协程的个数,然后创建 worker 协程; - worker 协程执行结束以后,都要调用
wg.Done()
; - main 协程调用
wg.Wait()
且被 block,直到所有 worker 协程全部执行结束后返回。
demo
举一个例子来说明这个问题
下面三个小demo可以实现同样的功能,但是下一个都比上一个更加的优雅
package main
import (
"fmt"
"sync"
)
// // 方法1
// func main() {
// for i := 0; i < 100; i++ {
// go fmt.Println(i)
// }
// time.Sleep(time.Second)
// }
// // 方法2
// func main() {
// num := 100
// c := make(chan bool, num)
// for i := 0; i < num; i++ {
// go func(i int) {
// fmt.Println(i)
// c <- true
// }(i)
// }
// for i := 0; i < num; i++ {
// <-c
// }
// }
// 方法3
func main() {
wg := sync.WaitGroup{
}
num := 20
wg.Add(num)
for i := 0; i < num; i++ {
go func(i int) {
// wg.Done() // 放这会有问题
fmt.Println(i)
// wg.Done()
}(i)
}
wg.Wait()
}
对于方法3来说,wg.Done()要放在写成结束之后,否则就会有问题
当wg.Done()放在位置1处,如下为两次运行代码的结果。可以看到,很可能在协程还没有开始运行,主进程就结束了
############## wg.Done()放在位置1处 ##############
# go run main.go
9
2
0
# go run main.go
9
0
1
2
3
4
5
6
7
8
wg.Done()放在位置2处就没有问题了,每次当协程运行结束之后才将waitGroup中的协程减1,就不会有影响了~