在 Go 语言中,var wg sync.WaitGroup 表示声明一个 sync.WaitGroup 类型的变量 wg,它用于等待一组 goroutine 完成执行。这是 Go 并发编程中常用的同步机制。
核心作用
sync.WaitGroup 通过计数器管理 goroutine 的等待:
Add(n):增加计数器值n(通常在启动 goroutine 前调用)Done():减少计数器值 1(在 goroutine 结束时调用)Wait():阻塞当前线程,直到计数器归零
使用步骤
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var wg sync.WaitGroup
for i := 1; i <= 3; i++ {
wg.Add(1) // 每个任务开始前增加计数器
go worker(i, &wg)
}
wg.Wait() // 阻塞直到所有任务完成
fmt.Println("所有任务完成")
}
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done() // 确保任务结束时减少计数器
fmt.Printf("Worker %d 开始工作\n", id)
time.Sleep(time.Second * time.Duration(id)) // 模拟耗时操作
fmt.Printf("Worker %d 完成\n", id)
}
关键注意事项
- 指针传递:必须传递
WaitGroup的指针(&wg),否则会复制副本导致死锁 Add的位置:建议在启动 goroutine 前调用Add,避免竞态条件defer Done():使用defer确保即使发生 panic 也会执行- 计数器匹配:
Add的总增量必须与Done的调用次数严格相等
典型应用场景
- 批量并发任务需要等待全部完成
- 并行计算后汇总结果
- 服务启动时需要等待多个初始化协程
错误示例分析
// 错误:未传递指针,导致死锁
var wg sync.WaitGroup
go func() {
wg.Done()
}()
wg.Wait()
// 正确:传递指针
var wg sync.WaitGroup
wg.Add(1)
go func(w *sync.WaitGroup) {
defer w.Done()
}(&wg)
wg.Wait()
通过合理使用 sync.WaitGroup,可以优雅地管理 Go 程序的并发流程。