go
runtime_error
ai_generated
true
panic: sync: WaitGroup 在上一次 Wait 返回前被复用
panic: sync: WaitGroup is reused before previous Wait has returned
ID: go/waitgroup-add-after-wait
80%修复率
89%置信度
0证据数
2024-03-22首次发现
版本兼容性
| 版本 | 状态 | 引入 | 弃用 | 备注 |
|---|---|---|---|---|
| 1.0+ | active | — | — | — |
根因分析
wg.Add() 与 wg.Wait() 并发调用。WaitGroup 约定要求所有增加计数器的 Add 调用必须先于观察到它们的 Wait。
English
wg.Add() is called concurrently with wg.Wait(). The WaitGroup contract requires all Add calls that increment the counter to happen-before the Wait that observes them.
解决方案
-
97% 成功率
var wg sync.WaitGroup for _, item := range items { wg.Add(1) go func(it Item) { defer wg.Done() process(it) }(item) } wg.Wait() -
96% 成功率
g, ctx := errgroup.WithContext(context.Background()) for _, item := range items { item := item g.Go(func() error { return process(ctx, item) }) } if err := g.Wait(); err != nil { return err }
无效尝试
常见但无效的做法:
-
80% 失败
The goroutine may start after Wait() already returned, so the counter never increments in time; still racy.
-
95% 失败
Timing-based synchronization is nondeterministic and fails under load or on fast machines.