最常用、最安全的非阻塞通道通信方式是 select + default;非阻塞发送时,若 channel 缓冲区满或无人接收,default 分支立即执行,避免 goroutine 阻塞。

Go 语言的 channel 本身是阻塞的,但通过 select + default 可以实现非阻塞收发,这是最常用、最安全的非阻塞通道通信方式。
非阻塞发送:用 select + default 避免卡住
向 channel 发送数据时,若缓冲区满或无人接收,会一直阻塞。加 default 分支可立即返回,不等待:
- 写法:在 select 中包含 send 操作,并配一个 default 分支
- 效果:若 channel 无法立刻接收,default 立即执行,不会挂起 goroutine
- 示例:select { case ch
非阻塞接收:同样靠 select + default 实现
从 channel 接收时,若无数据且无缓冲/无人发送,也会阻塞。default 让它“试试看,不行就走”:
- 写法:select 中写
- 注意:即使 channel 关闭,
- 安全做法:select { case x, ok :=
结合超时控制:避免无限等待
非阻塞不是唯一选择;有时你希望“最多等一会儿”。用 time.After 或 context.WithTimeout 更灵活:
立即学习“go语言免费学习笔记(深入)”;
- 超时接收:select { case x :=
- 适用场景:RPC 调用、心跳检测、用户操作响应等有明确时间边界的情况
- 优势:比纯 non-blocking 更可控,避免忙轮询浪费 CPU
慎用 close(ch) 后继续发送
channel 关闭后,再往里 send 会 panic。非阻塞发送不能掩盖这个错误:
- default 分支只是跳过阻塞,不解决语义错误
- 务必确保发送方清楚 channel 生命周期,或用 sync.Once / 状态标志配合管理
- 推荐模式:由单一 goroutine 负责关闭,其他 goroutine 只读/只写,配合 done channel 协调退出
基本上就这些。非阻塞本质是“不等”,核心就是 select + default;用对了,既能保持并发流畅,又不会因 channel 卡住整个流程。