go runtime_error ai_generated true

panic: send on closed channel

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

Also available as: JSON · Markdown · 中文
80%Fix Rate
90%Confidence
0Evidence
2024-02-11First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
1.x active — — —

Root Cause

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

中文

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

Workarounds

  1. 95% success
    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% success
    Use a separate done channel and select so senders bail out instead of sending after shutdown:
    select {
    case ch <- v:
    case <-done:
        return
    }

Dead Ends

Common approaches that don't work:

  1. 85% fail

    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% fail

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

  3. 80% fail

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