文章
go中sync.WaitGroup的用法
sync.WaitGroup 是等待多个并发任务完成的简洁方式
目录
在 Go 中,sync.WaitGroup 是一个非常常用的同步原语,用于等待一组 goroutine 执行完成。#
🧩 基本使用场景#
当你有多个 goroutine 并发执行任务,并希望主线程等待所有 goroutine 完成后再继续往下执行时,就用 WaitGroup。#
✅ 使用方式#
import (
"fmt"
"sync"
"time"
)
func main() {
var wg sync.WaitGroup // 创建 WaitGroup
for i := 1; i <= 3; i++ {
wg.Add(1) // 启动一个 goroutine 前加 1
go func(id int) {
defer wg.Done() // goroutine 结束时调用 Done
fmt.Printf("Goroutine %d starting\n", id)
time.Sleep(time.Second)
fmt.Printf("Goroutine %d done\n", id)
}(i)
}
wg.Wait() // 阻塞等待,直到计数归零
fmt.Println("All goroutines finished")
}
📌 方法说明#
| 方法 | 作用 |
| `Add(n int)` | 设置/增加等待的 goroutine 数量。通常在启动前调用。 |
| `Done()` | 当前 goroutine 结束时调用,表示完成了一个任务,相当于 `Add(-1)`。 |
| `Wait()` | 阻塞当前调用者,直到计数器归零(即所有任务完成)。 |
⚠️ 使用注意事项#
- Add 必须在 goroutine 启动之前调用
否则可能在 goroutine 启动前
Wait()已执行,造成提前结束。 - 不要在多个 goroutine 中同时调用 Add
Add()通常放在主 goroutine 或统一的地方管理,避免竞态。 - 避免 WaitGroup 复用
Wait()返回后,不要重用已用过的 WaitGroup,否则可能导致数据竞态或 panic。 - 不要忘记 Done()
每个
Add(1)必须有对应的Done(),否则Wait()永远阻塞。
🧠 示例:并发处理任务列表#
tasks := []int{1, 2, 3, 4, 5}
var wg sync.WaitGroup
for _, t := range tasks {
wg.Add(1)
go func(task int) {
defer wg.Done()
fmt.Println("Processing task:", task)
time.Sleep(500 * time.Millisecond)
}(t)
}
wg.Wait()
fmt.Println("All tasks processed")
✅ 总结#
sync.WaitGroup是等待多个并发任务完成的简洁方式;- 每个任务调用
Add(1),结束时Done(); Wait()会阻塞,直到所有 goroutine 都完成;- 使用简单但一定要注意正确调用
Add和Done的时机。