sync.WaitGroup 详细解释
sync.WaitGroup 是 Go 语言中用于同步多个 goroutine 的完成的工具。它允许主 goroutine 等待所有子 goroutine 执行完毕后再继续。
核心概念
WaitGroup 内部维护一个计数器:
- Add(n): 计数器加 n(通常在启动 goroutine 前调用)
- Done(): 计数器减 1(在 goroutine 完成时调用)
- Wait(): 阻塞直到计数器变为 0
基本用法
go
package main
import (
"fmt"
"sync"
"time"
)
func main() {
var wg sync.WaitGroup
// 添加 3 个 goroutine 到等待组
wg.Add(3)
// 启动第一个 goroutine
go func() {
defer wg.Done() // 完成时计数器 -1
fmt.Println("任务 1 开始")
time.Sleep(1 * time.Second)
fmt.Println("任务 1 完成")
}()
// 启动第二个 goroutine
go func() {
defer wg.Done()
fmt.Println("任务 2 开始")
time.Sleep(2 * time.Second)
fmt.Println("任务 2 完成")
}()
// 启动第三个 goroutine
go func() {
defer wg.Done()
fmt.Println("任务 3 开始")
time.Sleep(500 * time.Millisecond)
fmt.Println("任务 3 完成")
}()
// 等待所有 goroutine 完成
wg.Wait()
fmt.Println("所有任务完成!")
}
输出:
任务 1 开始
任务 2 开始
任务 3 开始
任务 3 完成
任务 1 完成
任务 2 完成
所有任务完成!
关键特性
| 方法 | 说明 |
|---|---|
Add(n) |
计数器加 n,必须在启动 goroutine 前调用 |
Done() |
计数器减 1,通常用 defer 确保执行 |
Wait() |
阻塞直到计数器为 0 |
常见模式
1. 批量处理任务
go
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
// 处理任务
fmt.Printf("处理任务 %d\n", id)
}(i)
}
wg.Wait()
注意事项
⚠️ 常见错误:
Add()调用晚于 goroutine 启动- 忘记调用
Done() Wait()前计数器已为 0
✅ 最佳实践:
- 使用
defer wg.Done()确保执行 - 在启动 goroutine 前调用
Add() - 避免在 goroutine 中调用
Add()