go
runtime_error
ai_generated
true
panic: 向已关闭的 channel 发送数据
panic: send on closed channel
ID: go/channel-send-on-closed
80%修复率
90%置信度
0证据数
2024-03-11首次发现
版本兼容性
| 版本 | 状态 | 引入 | 弃用 | 备注 |
|---|---|---|---|---|
| 1.0+ | active | — | — | — |
根因分析
某个 goroutine 在另一个 goroutine 已调用 close(ch) 之后执行 ch <- v。Go 会立即 panic,因为向已关闭 channel 发送永远是编程错误,而接收则会返回零值。
English
A goroutine calls ch <- v after another goroutine has already called close(ch). Go panics immediately because sending to a closed channel is always a programming error, unlike receiving which returns the zero value.
解决方案
-
92% 成功率
Make the sender the only owner of close. Use a done channel and select so senders never write after shutdown: select { case ch <- v: case <-done: return } -
80% 成功率
Use sync.Once for close and guard sends with a mutex + closed flag: mu.Lock() if !closed { ch <- v } mu.Unlock()
无效尝试
常见但无效的做法:
-
90% 失败
recover() only works in the same goroutine that is panicking, and even then it hides the race; the underlying close/send race remains and data is silently lost.
-
85% 失败
select default does not protect against a closed channel; a send case on a closed channel still panics when selected.