WaitGroup 用于等待 goroutine 完成,Add() 需在启动前调用且参数为正,Done() 必须与 Add() 严格匹配;defer wg.Done() 有 panic 导致漏调风险,应显式调用或确保 recover;不传递数据、不支持超时、零值可用但禁重复初始化。

WaitGroup 的基本用法和常见误用
WaitGroup 的核心作用是等待一组 goroutine 完成,不是锁、不传数据、不保证执行顺序。最常出错的是在 goroutine 启动前调用 Add() 却漏掉,或在 goroutine 内部多次调用 Done() 导致 panic。
-
Add()必须在启动 goroutine 之前调用,且参数为正整数;不能在 goroutine 内部调用(除非明确同步) -
Done()必须与Add()匹配,每个Add(1)对应一次Done();多调用会触发panic: sync: negative WaitGroup counter - 不能把
Wait()放在循环里等单个 goroutine——它会阻塞直到所有计数归零
WaitGroup 和 defer 的组合陷阱
很多人习惯在 goroutine 函数开头写 defer wg.Done(),看起来简洁,但存在隐性风险:如果函数提前 return 且未触发 defer(比如 panic 未被 recover),Done() 就不会执行,导致 Wait() 永远阻塞。
- 更稳妥的做法是在逻辑末尾显式调用
wg.Done(),尤其在有多个 return 路径时 - 若坚持用
defer,确保 goroutine 函数内无未捕获 panic,或在外层加 recover - 注意:
defer在 goroutine 中生效,不影响外层函数的WaitGroup状态
WaitGroup 不能替代 channel 的场景
WaitGroup 只解决“是否完成”,不解决“完成结果是什么”。当需要收集返回值、错误或按顺序处理输出时,必须配合 channel 使用。
1、数据调用该功能使界面与程序分离实施变得更加容易,美工无需任何编程基础即可完成数据调用操作。2、交互设计该功能可以方便的为栏目提供个性化性息功能及交互功能,为产品栏目添加产品颜色尺寸等属性或简单的留言和订单功能无需另外开发模块。3、静态生成触发式静态生成。4、友好URL设置网页路径变得更加友好5、多语言设计1)UTF8国际编码; 2)理论上可以承担一个任意多语言的网站版本。6、缓存机制减轻服务器
- 例如并发请求多个 API 并汇总响应:用
WaitGroup控制生命周期,用chan Result传递结果 - 不要试图通过全局变量 + WaitGroup 汇总数据——存在竞态,需额外加锁
- WaitGroup 的
Wait()不支持超时;要实现超时等待,得用sync.WaitGroup配合select+time.After或context.WithTimeout
WaitGroup 的零值可用,但别重复初始化
sync.WaitGroup 是值类型,零值可直接使用,不需要指针或 new()。但一旦开始使用,就不能再赋值或重新声明同名变量覆盖,否则旧实例丢失,Wait() 会永远卡住。
立即学习“go语言免费学习笔记(深入)”;
- 正确:
var wg sync.WaitGroup→wg.Add(2)→ 启动 goroutine - 错误:
wg := sync.WaitGroup{}在循环内重复声明,每次都是新实例,旧的无人Done() - 跨函数传递时,应传指针(
*sync.WaitGroup),否则值拷贝会导致计数不共享
Done() 是否一定被执行,往往只有压测或偶发失败时才暴露。









