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

Go是否保证先阻塞在channel上的goroutine会优先获取到数据?

Go channel阻塞goroutine的接收优先级问题

核心结论

先阻塞在channel上的goroutine不一定会优先获取到数据,你给出的代码行为不存在官方保证,第20行启动的goroutine也存在拿到数据的可能性,依赖接收顺序的逻辑是不严谨的。

具体说明

  • 语言规范层面

Go官方语言规范从未对channel接收者的调度优先级做出任何强制性约定,所有依赖goroutine接收channel顺序的代码都不符合语言规范的可移植性要求,可能在不同编译器、不同版本的Go运行时中表现不一致。

  • 当前主流实现的细节

目前常用的Go官方gc编译器中,无缓冲channel的等待goroutine队列确实采用FIFO策略维护,你提供的示例代码在绝大多数场景下运行时,都会是第16行启动的goroutine先拿到数据,但这仅仅是当前版本的实现细节,不是语言层面承诺的稳定特性,不应该作为代码逻辑的依赖依据。

  • 不可预测性的来源

即便当前实现是FIFO,你的代码也没有严格保障第16行的goroutine已经进入阻塞状态:time.Sleep只是暂停main goroutine的调度,极端场景下如果系统调度出现延迟,1秒后第16行启动的goroutine还没执行到<-c的阻塞步骤,反而第20行启动的goroutine先进入等待队列,就会是后者拿到数据。如果涉及带缓冲的channel、多channel select操作,调度的不确定性会更高。

示例代码

package main

import (
    "time"
    "fmt"
)

func g(c chan int) {
    v, ok := <-c
    fmt.Println(">>>", v, ok)
}

func main() {
    c := make(chan int)
    
    // Line 16
    go g(c)
    
    time.Sleep(1 * time.Second)
    
    // Line 20
    go g(c)
    
    c <- 233
    close(c)
    
    time.Sleep(1 * time.Second)
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 13:45:00