go runtime_error ai_generated true

panic: 向已关闭的 channel 发送数据

panic: send on closed channel

ID: go/channel-send-on-closed-channel

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

版本兼容性

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

根因分析

某个 goroutine 在另一个 goroutine 已调用 close(ch) 之后仍执行 ch <- v。运行时检测到向已关闭 channel 发送数据并 panic。常见于多个生产者共享一个 channel 且其中一个提前关闭,或 close 在所有发送者完成前被调用。

English

A goroutine calls ch <- v after another goroutine has already called close(ch). The runtime detects the send on a closed channel and panics. Common when multiple producers share a channel and one of them closes it, or when close is called before all senders finish.

generic

解决方案

  1. 95% 成功率
    Only the single owner (or a dedicated closer) closes the channel after all producers are done, using a sync.WaitGroup:
    var wg sync.WaitGroup
    for _, p := range producers { wg.Add(1); go func(p P){ defer wg.Done(); for v := range p { ch <- v } }(p) }
    go func(){ wg.Wait(); close(ch) }()
  2. 88% 成功率
    Use a separate done channel and select so senders bail out instead of sending after shutdown:
    select {
    case ch <- v:
    case <-done:
        return
    }

无效尝试

常见但无效的做法:

  1. 85% 失败

    recover only works in the same goroutine that panicked and masks a genuine ownership bug; the channel stays closed so subsequent sends still panic.

  2. 90% 失败

    Non-deterministic; under load the close can still race ahead of the send. Sleeps do not establish ordering.

  3. 80% 失败

    Closing an already-closed channel panics with 'close of closed channel', trading one panic for another.