Go WaitGroup
3 min
Go等待组(WaitGroup)
1. 什么是等待组
WaitGroup是 Go 语言标准库sync包提供的一个结构体,用于等待一组goroutine完成执行。- 它允许主
goroutine等待多个其他goroutine完成它们的任务,然后再继续执行。
2. 为什么需要等待组
在并发编程中,经常需要在主 goroutine 等待所有子 goroutine 完成任务后再继续进行下一步操作。如果没有等待组,就需要自己管理计数器和锁,来确保所有子 goroutine 完成。这不仅容易出错,而且复杂。WaitGroup 提供了一个简洁的方法来解决这个问题。
- 使用场景
同步多个
goroutine:在需要同步等待多个并发任务完成时,使用WaitGroup。并行处理:例如,下载多个文件或处理多个请求时,主
goroutine可以等待所有下载或处理完成后再继续执行。
3. 如何使用等待组
使用 WaitGroup 主要涉及三个方法:
Add(delta int):添加等待计数器的值。- 传入参数是增加等待组的值,
Add(3)就是增加3个
- 传入参数是增加等待组的值,
Done():减少等待计数器的值,表示某个goroutine已经完成。Wait():阻塞直到等待计数器变为零。
4. 示例代码
package main
import (
"fmt"
"sync"
"time"
)
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done() // 确保在函数结束时调用 Done
fmt.Printf("Worker %d starting\n", id)
time.Sleep(time.Second) // 模拟工作
fmt.Printf("Worker %d done\n", id)
}
func main() {
var wg sync.WaitGroup
const numWorkers = 5
for i := 1; i <= numWorkers; i++ {
wg.Add(1) // 每启动一个 goroutine,计数器加 1
go worker(i, &wg)
}
wg.Wait() // 等待所有 goroutine 完成
fmt.Println("All workers done")
}4.1 注意事项
- 计数匹配:确保
Add和Done的调用数量匹配。每次Add(1)必须有相应的Done()调用。 - 引用传递:将
*sync.WaitGroup的指针传递给goroutine,而不是值传递。 - 不要嵌套
WaitGroup:一个WaitGroup不应被多个父goroutine同时等待。
5. 总结
WaitGroup 是 Go 语言中一个强大而简单的并发工具,用于协调多个 goroutine 的执行。它的使用能够有效简化并发编程中的同步问题,使代码更清晰和易于维护。在涉及并发任务时,WaitGroup 是一个非常有用的工具。