英文源地址
为了等待多个goroutine完成, 我们可以使用WaitGroup.
package main
import (
"fmt"
"sync"
"time"
)
// 这个函数我们将在每个goroutine中运行
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用于等待这里启动的所有协程完成.
// 注意: 如果WaitGroup显式地传递给函数, 它应该通过指针进行.
var wg sync.WaitGroup
// 启动几个协程, 并为每个协程在WaitGroup计数器中进行增加
for i := 1; i <= 5; i++ {
wg.Add(1)
// 避免在每个协程闭包中重复使用相同的值.具体细节可以参考FAQ
i := i
// 将worker调用包装在闭包中, 确保告诉WaitGroup这个worker已经完成.
// 这样, 工作协程不必直到其执行中涉及的并发原语.
go func() {
defer wg.Done()
worker(i)
}()
}
// 阻塞, 直到WaitGroup计数器返回0;所有worker都通知已完成.
wg.Wait()
// 请注意, 这种方法没有直接的方法从worker中传递error.对于更进阶的用例, 请参考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
对于每次调用, worker协程的启动和结束顺序可能不一样.
下一节将介绍: Rate Limiting速率控制.