# panic: 向已关闭的 channel 发送数据

- **ID:** `go/channel-send-on-closed-channel`
- **领域:** go
- **类别:** runtime_error
- **验证级别:** ai_generated
- **修复率:** 80%

## 根因

某个 goroutine 在另一个 goroutine 调用 close(ch) 之后仍执行 ch <- val。向已关闭 channel 发送数据必定 panic，发送方与关闭方之间的竞态是根本原因。

## 版本兼容性

| 版本 | 状态 | 引入 | 弃用 |
|------|------|------|------|
| 1.0+ | active | — | — |

## 解决方案

1. **** (95% 成功率)
   ```
   done := make(chan struct{})
// producer owns close
func producer(ch chan int, done <-chan struct{}) {
    defer close(ch)
    for i := 0; ; i++ {
        select {
        case <-done:
            return
        case ch <- i:
        }
    }
}
   ```
2. **** (90% 成功率)
   ```
   select {
case ch <- v:
case <-quit:
    return
}
   ```

## 无效尝试

- **** — recover only stops the panic in the current goroutine; the send is logically invalid and the message is silently lost, corrupting downstream logic. Also recover does not work across goroutine boundaries. (90% 失败率)
- **** — Sleep does not establish happens-before ordering; the scheduler may still run the closer after the sender. It only narrows the race window and fails under load. (85% 失败率)
