go runtime_error ai_generated true

恐慌:关闭已关闭的通道(在 for range 中)

panic: close of closed channel (in for range)

ID: go/goroutine-for-range-channel-close

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

版本兼容性

版本状态引入弃用备注
1.20 active
1.21 active

根因分析

关闭正在被另一个协程 range 的通道,导致 range 尝试从已关闭通道读取时引发恐慌。

English

Closing a channel that is being ranged over by another goroutine, causing a panic when the range attempts to read from the closed channel.

generic

解决方案

  1. 100% 成功率 Use a separate goroutine to close the channel after all sends are done.
    ch := make(chan int)
    go func() {
        for i := 0; i < 10; i++ {
            ch <- i
        }
        close(ch)
    }()
    for v := range ch {
        fmt.Println(v)
    }
  2. 95% 成功率 Use a sync.WaitGroup to coordinate closure.
    var wg sync.WaitGroup
    wg.Add(1)
    go func() {
        defer wg.Done()
        for i := 0; i < 10; i++ {
            ch <- i
        }
    }()
    go func() {
        wg.Wait()
        close(ch)
    }()
    for v := range ch {
        fmt.Println(v)
    }

无效尝试

常见但无效的做法:

  1. Closing the channel inside the range loop. 80% 失败

    Range loop continues until channel is closed, but closing inside causes panic on next iteration.

  2. Using a defer close in the sender goroutine that ranges. 70% 失败

    If the sender is also the range receiver, closing inside the loop is problematic.