在线文档 > Golang练习 > WaitGroup
在Go中,要等待多个 协程 完成,我们可以使用一个wait group(等待组)。
package main
import (
"fmt"
"sync"
"time"
)
// 这是我们将在每个协程中运行的函数。
func worker(id int) {
fmt.Printf("Worker %d starting\n", id)
// 休眠以模拟一项耗时的任务。
time.Sleep(time.Second)
fmt.Printf("Worker %d done\n", id)
}
func main() {
// 这个 WaitGroup 用于等待此处启动的所有goroutine完成。
// 注意:如果WaitGroup显式传递到函数中,它应该是 `指针`。
var wg sync.WaitGroup
// 启动几个协程,并为每个WaitGroup添加计数器。
for i := 1; i <= 5; i++ {
wg.Add(1)
// Avoid re-use of the same `i` value in each goroutine closure.
// See [the FAQ](https://golang.org/doc/faq#closures_and_goroutines)
// for more details.
// 避免在每个 协程 闭包中重用相同的`i`值。
// 更多细节请参见 [常见问题解答]。
i := i
// 将worker调用包装在一个闭包中,确保告诉WaitGroup这个worker已经完成。
// 这样,worker本身不必意识到涉及其执行的并发原语。
go func() {
defer wg.Done()
worker(i)
}()
}
// 一直阻塞,直到WaitGroup计数器回到0;所有worker都通知他们已经完成。
wg.Wait()
}
请注意,wg.Wait()
这种方法没有一种直接的方式从worker那里传递错误。对于更高级的用例,请考虑使用errgroup包。
常见问题解答。
运行结果如下:
$ go run waitgroups.go
Worker 5 starting
Worker 3 starting
Worker 4 starting
Worker 1 starting
Worker 2 starting
Worker 4 done
Worker 1 done
Worker 2 done
Worker 5 done
Worker 3 done
对于每个调用,启动和完成的工作线程的顺序可能不同。