Go Runtime(八):Channel与Select

本文源码基线为 Go 1.26.2、Linux/amd64。Channel 的语言语义跨平台一致;文中的字段、函数和行号固定到该版本,后续版本可能调整实现。 Channel 不是“带锁队列”的同义词。它同时实现值传递、goroutine 阻塞与唤醒、close 广播、select 多路竞争,并且要和栈复制、GC、race detector、Timer 配合。 理解 Channel 的关键,是区分三种正常数据路径:直接交接、环形缓冲区、等待队列。前两条可以立即完成;进入等待队列才会把当前 G 变为 _Gwaiting。nil Channel 的阻塞操作是没有数据路径的永久 park,属于另一个边界情况。 从语法到runtime入口 编译器把普通发送和接收分别降低为 runtime.chansend1、runtime.chanrecv1/2。非阻塞的单 case select 会被优化为 selectnbsend 或 selectnbrecv;多个有效 case 才构造 case 数组并调用 runtime.selectgo。 GOch <- x // runtime.chansend1 x = <-ch // runtime.chanrecv1 x, ok = <-ch // runtime.chanrecv2 close(ch) // runtime.closechan 这意味着 select 不是对每个 case 依次执行一次普通 channel 操作。它必须在所有相关 Channel 锁的保护下完成一次原子决策。 源码入口:walk/select.go 与 chan.go。 hchan保存什么 hchan 是 Channel 的运行时对象: ...

August 18, 2026