You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言select中非阻塞写channel操作的行为疑问

Go无缓冲Channel在select中的发送行为解析

先看你给出的代码:

func main() {
    ch := make(chan int)

    select {
    case ch <- 42:
        fmt.Println("Sent value to channel")
    default:
        fmt.Println("Channel is not ready for sending")
    }

    select {
    case value := <-ch:
        fmt.Println("Received value from channel:", value)
    default:
        fmt.Println("Channel is not ready for receiving")
    }
}

针对你的疑问:写操作ch <- 42从未被执行,直接触发了default分支,原因如下:

  • 你创建的是无缓冲Channel(make(chan int)默认无缓冲),这类Channel的发送规则是:必须有一个已准备好的接收goroutine,发送操作才能立即完成,否则当前goroutine会被阻塞。
  • 这段代码里只有main一个goroutine,没有其他goroutine在等待接收ch的值,所以ch <- 42这个操作无法立即完成。
  • select语句的逻辑是:先检查所有case对应的操作是否能立即执行,如果没有任何case满足,就会执行default分支(如果存在的话)。这里发送操作无法立即完成,所以直接进入default,发送行为根本没发生。

补充验证:如果在select前启动一个goroutine负责接收,发送case就会被执行:

func main() {
    ch := make(chan int)
    // 启动一个goroutine等待接收
    go func() {
        <-ch
    }()

    select {
    case ch <- 42:
        fmt.Println("Sent value to channel")
    default:
        fmt.Println("Channel is not ready for sending")
    }
}

此时代码会打印Sent value to channel,因为有接收方准备好,发送操作可以立即完成。

回到原代码的第二个select,同样因为没有发送方准备好,接收操作无法立即完成,所以也会走default分支。

内容的提问来源于stack exchange,提问作者Ram Dittakavi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 18:04:58