go runtime_error ai_generated true

panic: sync: WaitGroup 计数器为负数

panic: sync: negative WaitGroup counter

ID: go/sync-waitgroup-negative-counter

其他格式: JSON · Markdown 中文 · English
80%修复率
89%置信度
0证据数
2024-02-14首次发现

版本兼容性

版本状态引入弃用备注
1.x active — — —

根因分析

wg.Done() 调用次数大于 wg.Add(n),常见于在未 Add 的 goroutine 中调用 Done,或 Wait 返回后才调用 Add。

English

wg.Done() is called more times than wg.Add(n), often because Done is called in a goroutine that was never added, or Add is called after Wait has already returned.

generic

解决方案

  1. 97% 成功率
    for _, item := range items {
        wg.Add(1)
        go func(it Item) {
            defer wg.Done()
            process(it)
        }(item)
    }
    wg.Wait()
  2. 95% 成功率
    g, ctx := errgroup.WithContext(ctx)
    for _, it := range items {
        it := it
        g.Go(func() error { return process(ctx, it) })
    }
    if err := g.Wait(); err != nil { return err }

无效尝试

常见但无效的做法:

  1. 70% 失败

    Race with wg.Wait(): Wait may return before Add runs, then Done panics or Wait returns early.

  2. 75% 失败

    Hides the bug; the WaitGroup is now inconsistent and Wait may hang or return prematurely.