go
runtime_error
ai_generated
true
panic: sync: WaitGroup is reused before previous Wait has returned
ID: go/waitgroup-add-after-wait
80%Fix Rate
89%Confidence
0Evidence
2024-03-22First Seen
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| 1.0+ | active | — | — | — |
Root Cause
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.
generic中文
wg.Add() 与 wg.Wait() 并发调用。WaitGroup 约定要求所有增加计数器的 Add 调用必须先于观察到它们的 Wait。
Workarounds
-
97% success
var wg sync.WaitGroup for _, item := range items { wg.Add(1) go func(it Item) { defer wg.Done() process(it) }(item) } wg.Wait() -
96% success
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 }
Dead Ends
Common approaches that don't work:
-
80% fail
The goroutine may start after Wait() already returned, so the counter never increments in time; still racy.
-
95% fail
Timing-based synchronization is nondeterministic and fails under load or on fast machines.