chan

只读通道的声明语法:chan 和 <code> 到底谁是谁
Go 里通道方向是类型的一部分,不是运行时约束。写成 chan 表示“只能发”,<code> 表示“只能收”。注意箭头永远指向数据流动方向:数据从发送端流向接收端,所以 <code>chan 的箭头朝外(往外发),<code> 的箭头朝内(往里收)。
常见错误是记反箭头位置,比如写成 chan int(语法错误)或把 <code> 当成可发送——编译器会直接报错:<code>invalid operation: cannot send to receive-only channel。
func worker(infunc sender(out chanfunc bad(in
为什么不能把双向通道直接传给只读/只写形参
双向通道 chan int 可以隐式转换为 或 <code>chan,但反过来不行。这是类型安全设计:你总能用一个“能收能发”的通道去替代“只收”或“只发”的角色,但不能让一个“只收”的通道突然被用来发数据。
典型场景是主协程创建双向通道,然后分别传给生产者(只写)和消费者(只读)。如果强行传 给期望 <code>chan int 的函数,会编译失败:cannot use c (type 。
立即学习“go语言免费学习笔记(深入)”;
- 允许:
c := make(chan int); f(c) // f 接收 - 禁止:
c := make( - 双向通道变量名本身不带方向,方向只在类型声明中体现
使用 close() 时必须确保是发送端操作
只有发送端(即类型为 chan 或 <code>chan T)才能调用 close();接收端()调用会编译失败:<code>invalid operation: close(c) (channel is receive-only)。
这很关键——如果你把通道转成 后交给多个 <a style="color:#f60; text-decoration:underline;" title="go" href="https://www.php.cn/zt/15863.html" target="_blank">go</a>routine,它们都无法关闭它。关闭责任必须由创建通道或明确拥有发送权限的一方承担,通常在生产者结束时调用。
- ✅ 正确:生产者函数接收
chan,循环结束后 <code>close(out) - ❌ 错误:消费者函数接收
,试图 <code>close(in) - ⚠️ 注意:
close()不影响已存在的接收操作,但后续接收会立即返回零值+false
泛型函数里怎么保持通道方向性
泛型函数参数若声明为 ch ,调用时传入 <code>chan T 没问题,但传入 就可能触发类型推导失败,尤其当函数内部还做了类型断言或反射操作时。
更稳妥的做法是显式指定类型参数,或在函数签名中接受接口式抽象(比如用函数代替通道),但多数情况下,只要别在泛型约束里强行要求 ~chan 这种具体方向类型,就很少踩坑。
- 推荐:
func drain[T any](ch - 避免:
func pipe[T any, C ~chan —— 约束过死,实际难以传入 - 泛型不会改变方向规则,只是让类型推导更敏感
方向控制是编译期行为,不产生运行时代价,但一旦写错方向,编译器报错信息可能不够直白——比如提示“cannot use as type”,而不是“你试图往只读通道写”。最易忽略的是 close 的权限归属,以及泛型中对方向类型的过度约束。










