WaitGroup用于等待多个协程完成,通过Add增加计数、Done减少计数、Wait阻塞直至计数为零,主协程可据此同步子协程执行。

在Go语言中,WaitGroup 是 sync 包提供的一个同步原语,用于等待一组并发的协程(goroutine)执行完成。它特别适用于主协程需要等待多个子协程结束的场景,比如批量任务处理、并行请求等。
WaitGroup 的基本机制
WaitGroup 内部维护一个计数器,通过三个方法来控制:
- Add(n):增加计数器的值,表示要等待 n 个协程
- Done():在协程结束时调用,相当于 Add(-1),将计数器减一
- Wait():阻塞当前协程,直到计数器变为 0
典型使用模式是:主协程调用 Add 设置任务数量,每个子协程执行完任务后调用 Done,主协程通过 Wait 阻塞等待所有任务完成。
实际使用示例
下面是一个简单的例子,展示如何用 WaitGroup 管理5个并发协程:
立即学习“go语言免费学习笔记(深入)”;
package main
import (
"fmt"
"sync"
"time"
)
func worker(id int, wg *sync.WaitGroup) {
defer wg.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
for i := 1; i <= 5; i++ {
wg.Add(1) // 增加等待计数
go worker(i, &wg) // 启动协程
}
wg.Wait() // 等待所有协程完成
fmt.Println("All workers finished")
}
在这个例子中,main 函数启动5个 worker 协程,每个都传入同一个 WaitGroup 指针。使用 defer wg.Done() 确保即使发生 panic 也能正确通知完成。
从一个Perl爱好者到一个Perl程序员。《Intermediate Perl》将教您如何把Perl作为编程语言来使用,而不仅只是作为一种脚本语言。 Perl是一种灵活多变、功能强大的编程语言,可以应用在从系统管理到网络编程再到数据库操作等很多方面。人们常说Perl让容易的事情变简单、让困难的事情变得可行。《Intermediate Perl》正是关于如何将技能从处理简单任务跃升到胜任困难任务的书籍。 本书提供对Perl中级编程优雅而仔细的介绍。由畅销的《学习Perl》作者所著,本书提供了《学习P
使用注意事项
虽然 WaitGroup 简单易用,但有几个关键点需要注意:
- 确保 Add 的调用在 Wait 之前完成,否则可能引发 panic
- 每次 Add 的值必须大于 0,Add(0) 不会改变状态
- WaitGroup 不是可复制类型,应通过指针传递给协程
- 不要在多个协程中同时调用 Add,除非有额外同步保护
常见错误是把 Add 放在 goroutine 内部调用,这可能导致主协程还没来得及增加计数就进入 Wait,造成逻辑错乱。
适用场景与替代方案
WaitGroup 适合已知任务数量且只需等待完成的场景。如果任务数量动态变化或需要传递结果,可以结合 channel 使用。对于更复杂的协调需求,如超时控制,可以考虑使用 context 包配合 WaitGroup。
基本上就这些。WaitGroup 虽小,但在并发控制中非常实用,掌握它的正确用法能让 Go 并发编程更安全高效。









