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

Go channel写入顺序保证:select多case是否优先执行先就绪的通道

问题解答

前置说明

你给出的代码存在两处可直接导致运行异常的笔误/逻辑问题:

  • 子goroutine中的fmr.Println应为fmt.Println,否则会编译报错
  • 全程没有对done通道执行写入或者关闭操作,程序最终会永久阻塞在主goroutine的<-done语句,无法正常退出
    以下讨论基于修正上述问题后的代码展开。

核心问题答复

1. 程序是否保证永远打印"ch1"?

不保证,存在打印"ch2"的可能性。

2. 为什么第二个case可能先执行?

这里的关键在于Go调度器的调度时机以及select语句的执行规则:

  • 主goroutine执行<-ready之后,子goroutine已经进入select阻塞状态,等待任意一个case就绪
  • 主goroutine先执行ch1 <- struct{}{},此时ch1的读case就绪;接下来执行close(ch2),已关闭的通道永远可以读,因此ch2的读case也进入就绪状态
  • 存在两种可能的调度时序:
    • 第一种:主goroutine写完ch1之后,子goroutine立刻被调度唤醒,此时ch2还未关闭,只有ch1的case就绪,因此打印"ch1"
    • 第二种:主goroutine写完ch1之后没有发生调度,连续执行完close(ch2),之后子goroutine才被调度唤醒,此时两个case都处于就绪状态,select会随机选择一个执行,就有可能选到ch2的case

3. 官方与源码依据

  • 官方规范:Go语言官方规范中明确说明,当select语句同时有多个可执行的case时,运行时会伪随机选择其中一个执行,不存在优先级排序。
  • 源码实现:Go runtime层的select实现逻辑中,会先收集所有就绪的case,打乱顺序后选择第一个执行,没有按照case定义顺序选择的逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 05:54:01