go
runtime_error
ai_generated
true
恐慌:关闭已关闭的通道(在 for range 中)
panic: close of closed channel (in for range)
ID: go/goroutine-for-range-channel-close
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.
解决方案
-
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) } -
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) }
无效尝试
常见但无效的做法:
-
Closing the channel inside the range loop.
80% 失败
Range loop continues until channel is closed, but closing inside causes panic on next iteration.
-
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.