Go的channel是协程间同步通信机制而非队列;不关闭也能传数据,但易致goroutine泄漏或死锁;声明须指定类型如chan int,发送用ch

Go 的 channel 不是队列,而是协程间同步的通信机制;不关闭也能正常传递数据,但不关闭可能引发 goroutine 泄漏或死锁。
channel 基本声明与发送/接收写法
声明时必须指定元素类型,chan int 和 chan(只发)或 <code>(只收)语义不同,混用会编译报错。零值为 <code>nil,对 nil channel 发送或接收会永久阻塞。
- 无缓冲 channel:
ch := make(chan int),发送和接收必须配对发生,否则阻塞 - 有缓冲 channel:
ch := make(chan int, 2),缓冲满才阻塞发送,缓冲空才阻塞接收 - 发送写法统一为:
ch ;接收写法:<code>x := 或 <code>x, ok := (带关闭状态检查)
如何安全关闭 channel 并避免 panic
只有 sender(发送方)能关闭 channel;receiver 关闭会编译失败。重复关闭会 panic:panic: close of closed channel。关闭后仍可接收剩余数据,但之后每次接收都返回零值 + ok=false。
- 典型模式:用
sync.WaitGroup确保所有 sender 完成后再关闭,例如多个 goroutine 写入同一 channel 后由主 goroutine 关闭 - 不要在循环中边读边关:
for v := range ch { ... }自动在 channel 关闭后退出,无需手动判断ok - 避免在 select 中关闭 channel——
case ch 是发送操作,<code>case close(ch):是非法语法
range 遍历 channel 的隐含行为与陷阱
for range ch 等价于持续接收直到 channel 关闭且缓冲耗尽。它不会检测 channel 是否为 nil,遇到 nil 会永久阻塞。
立即学习“go语言免费学习笔记(深入)”;
- 如果 sender 永远不关闭 channel,
range永不结束,goroutine 卡住 - 如果 sender 关闭过早(比如还没发完),receiver 可能漏掉数据
- 想提前退出?加
break或用带donechannel 的select控制生命周期,而不是依赖range
真正难的不是“怎么写”,而是判断谁负责关闭、何时关闭、是否所有 receiver 都已退出——这些靠代码结构约束,没法靠语法强制。


















