单向通道的读取行为受类型系统严格约束:只有 chan

Go 里读取 channel 的动作本身没有方向限制,但「单向通道」的读取行为受类型系统严格约束:只有 类型才允许接收操作,<code>chan 类型连编译都过不了。
怎么从
声明为 的变量只能用于接收,不能发送或关闭。读取方式和双向 channel 一致,但编译器会拦住所有非法操作:
v := —— 合法,正常接收ch —— 编译错误:<code>invalid operation: ch-
close(ch)—— 编译错误:cannot close receive-only channel
常见错误现象是把双向 channel 传给只接受 的函数后,在函数内部又试图保留原始引用做写入——这说明你没真正隔离作用域。
为什么
make( 会报错:<code>cannot make type 。Go 不允许直接创建单向通道实例,因为底层必须可读可写才有意义。
-
make(chan int)是唯一合法的初始化方式 ro := 是标准转换写法,必须显式类型转换- 省略类型(如
ro := ch)会失败,因为 Go 不做隐式方向转换
试图绕过这个限制(比如用 interface{} 包一层再反射取值)就等于放弃类型安全,单向约束彻底失效。
for-range 遍历
可以用 for v := range ch 遍历 ,但要注意:
- channel 必须被某处
close(),否则循环永不退出 - 遍历过程中仍不允许
ch 或 <code>close(ch) - 如果上游 goroutine 意外 panic 未关闭 channel,接收方会永久阻塞(无缓冲)或卡在最后一次有效值上(有缓冲)
更稳妥的做法是配合 select + default 或带超时的 time.After,避免单点故障拖垮整个流程。
最容易被忽略的一点:单向通道的安全性完全依赖「不暴露双向引用」。哪怕只在某个闭包里多写了一行 _ = ch(其中 ch 是原始 chan int),那个 goroutine 就拥有了越权写入能力。约束不是加在通道上,而是加在变量类型和作用域上。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











