go
runtime_error
ai_generated
true
panic: 向已关闭的 channel 发送数据
panic: send on closed channel
ID: go/send-on-closed-channel
80%修复率
88%置信度
0证据数
2024-02-19首次发现
版本兼容性
| 版本 | 状态 | 引入 | 弃用 | 备注 |
|---|---|---|---|---|
| 1.19 | active | — | — | — |
| 1.20 | active | — | — | — |
| 1.22 | active | — | — | — |
根因分析
生产者 goroutine 在另一个 goroutine 关闭 channel 后仍发送数据。通常是 defer 中的 close 与仍在运行的兄弟生产者竞争。
English
A producer goroutine sends to a channel after another goroutine has closed it. Usually a close in a defer while sibling producers are still running.
解决方案
-
97% 成功率
var wg sync.WaitGroup for i := 0; i < n; i++ { wg.Add(1) go func(id int) { defer wg.Done() for v := range src(id) { out <- v } }(i) } go func() { wg.Wait(); close(out) }() -
92% 成功率
select { case out <- v: case <-done: return }
无效尝试
常见但无效的做法:
-
85% 失败
The check-then-send is not atomic; a close can land between the check and the send.
-
70% 失败
Recover silences the crash but the message is silently dropped; downstream logic may hang waiting for it.