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

Go语言无缓冲channel读写多个值的运行机制是什么?

问题解答

认知修正

首先纠正一个常见的理解误区:无缓冲channel的缓冲区大小为0,根本无法容纳任何值,并非你理解的能容纳1个值。所有对无缓冲channel的写入操作,都会直接阻塞直到有接收方准备好接收该值,数据直接从发送方Goroutine拷贝到接收方Goroutine,不会在channel中暂存。


疑问1:writeToChan为何能写入3个值?

你的代码中刚好存在3个独立的接收操作:

  • rdFrmChan Goroutine中的1次读操作
  • main Goroutine中的2次读操作

三次写入刚好对应三次读取:writeToChan每写入一个值就会阻塞,直到某个接收方把值读走才会继续执行下一次写入,因此三次写入都能正常完成,不会永久阻塞。


疑问2:为何读取顺序和写入顺序不一致?

当writeToChan结束1秒休眠开始写入第一个值时,rdFrmChan的读操作、main的第一个读操作已经同时处于阻塞等待channel数据的状态。
Go runtime对于多个接收者同时等待同一个无缓冲channel发送的场景,会随机选择一个接收者来接收当前发送的值,不会按照接收者启动/阻塞的顺序分配。
你给出的运行结果对应的调度逻辑是:

  1. 第一次写入42,被main的第一个读操作抢到,因此main打印main read 1 -: 42,之后main阻塞在第二个读操作
  2. 第二次写入27,被rdFrmChan的读操作抢到,因此打印Go routine read : 27,rdFrmChan执行结束退出
  3. 第三次写入9,只有main的第二个读操作在等待,因此main打印main read 2 -: 9

这个输出结果不是固定的,多次运行可能会出现不同的顺序,属于正常现象。


接收方会一直阻塞,直到有数据可接收。如果是无缓冲channel,发送方会阻塞直到接收方接收了值。如果是带缓冲的channel,发送方仅在值被拷贝到缓冲区前阻塞;若缓冲区已满,则需要等待直到有接收方取走值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 22:06:03