go runtime_error ai_generated true

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

panic: send on closed channel

ID: go/channel-send-on-closed-channel

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

版本兼容性

版本状态引入弃用备注
1.0+ active

根因分析

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

English

A goroutine executed ch <- val after another goroutine called close(ch). Sending on a closed channel always panics; the race between sender and closer is the root issue.

generic

解决方案

  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
    }

无效尝试

常见但无效的做法:

  1. 90% 失败

    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.

  2. 85% 失败

    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.