waitgroup 本身不阻塞协程,仅作计数器;主协程卡住通常因 add() 调用时机/次数错误或漏调 done(),add() 必须在启动 goroutine 前调用,且每启一个加 1,子协程末尾须用 defer wg.done()。

WaitGroup 本身不阻塞协程,它只是计数器;主协程卡住,几乎一定是 WaitGroup.Add() 调用时机或次数错了,或者漏了 Done()。
WaitGroup 必须在启动 goroutine 前调用 Add()
常见错误是把 Add() 放在 goroutine 内部——此时主协程可能已执行到 Wait(),而计数器还是 0,直接返回,子协程还在跑,程序提前退出。
正确做法:
- 先用
var wg sync.WaitGroup声明 - 在
go func() { ... }()之前,调用wg.Add(1)(每启一个子协程加 1) - 子协程末尾必须调用
wg.Done()(建议用defer wg.Done()防遗漏)
示例:
var wg sync.WaitGroup for i := 0; i <h3>不能复用未重置的 WaitGroup</h3><p><code>WaitGroup</code> 不是“一次性”对象,但它的计数器归零后,**不能直接再次 <code>Add()</code>** ——Go 1.20+ 会 panic:<code>sync: negative WaitGroup counter</code>。旧版本可能静默出错。</p><div class="aritcle_card flexRow artxards"> <div class="artcardd flexRow"> <a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2500" title="度加AI"><img src="https://img.php.cn/upload/manual/000/969/633/6a61700fe297c535.jpg" alt="度加AI" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a> <div class="aritcle_card_info flexColumn"> <a rel="nofollow" href="/xiazai/gongju/2500" title="度加AI" class="overflowclass">度加AI</a> <p class="overflowclass">度加AI官网入口,百度官方 AIGC 创作平台,支持 AI 成片、AI 生文、数字人、声音克隆、配音字幕与智能剪辑等在线创作能力。</p> </div> <a rel="nofollow" href="/xiazai/gongju/2500" title="度加AI" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a> </div> </div><p>如果你需要多次等待不同批任务:</p>
- 每次用新变量:
wg1 := sync.WaitGroup{}、wg2 := sync.WaitGroup{} - 或显式重置:
var wg sync.WaitGroup→ 执行完wg.Wait()后,不能再用;需重新声明,或用reflect.ValueOf(&wg).Elem().FieldByName("counter").SetInt(0)(不推荐,属未公开字段) - 更安全的做法:封装成函数,让
WaitGroup在函数作用域内生命周期清晰
WaitGroup 无法捕获 panic,也不处理错误传播
WaitGroup 只管“是否结束”,不管“是否成功”。如果某个子协程 panic,Wait() 仍会返回(因为 Done() 已执行),但主协程可能被 panic 中断(若没 recover)。
需要错误协调时:
- 用
chan error收集子协程错误(记得 close 或带缓冲避免阻塞) - 或搭配
errgroup.Group(标准库golang.org/x/sync/errgroup),它内置WaitGroup逻辑且支持错误传递和上下文取消 - 不要试图在
WaitGroup上加锁或嵌套等待——它不是锁,也不是信号量
最常被忽略的一点:WaitGroup 的零值可用,但 Add() 和 Done() 是并发安全的,Wait() 却**不能在多个 goroutine 中同时调用**——它只应由主协程(或唯一等待者)调用一次。多处 Wait() 可能导致竞态或死锁。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










