go runtime_error ai_generated true

panic: receive from closed channel (in range)

ID: go/goroutine-range-over-closed-channel

Also available as: JSON · Markdown · 中文
80%Fix Rate
84%Confidence
0Evidence
2024-06-18First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
1.0 active
1.20 active

Root Cause

Iterating over a channel with range after it has been closed; range receives zero values until channel is drained.

generic

中文

在通道关闭后使用range迭代;range会接收零值直到通道耗尽。

Workarounds

  1. 95% success Use for with ok pattern instead of range
    for {
        val, ok := <-ch
        if !ok {
            break
        }
        // process val
    }
  2. 90% success Ensure channel is closed only after all sends are done
    var wg sync.WaitGroup
    for i := 0; i < 5; i++ {
        wg.Add(1)
        go func() {
            defer wg.Done()
            ch <- i
        }()
    }
    wg.Wait()
    close(ch)
    for val := range ch {
        // process
    }

Dead Ends

Common approaches that don't work:

  1. Using recover() to catch panic from zero value 90% fail

    Range over closed channel doesn't panic; it returns zero values, which may cause logic errors.

  2. Checking channel length before range 80% fail

    len(ch) doesn't indicate closed state; closed channel can have buffered data.