只有发送方能调用 close,且必须确保通道非 nil、未关闭;否则运行时 panic;仅双向通道(chan t)和只写通道(chan

只有发送方能调用 close,且必须确保通道非 nil、未关闭;否则运行时 panic。
哪些通道类型允许调用 close
仅双向通道(chan T)和只写通道(chan)可被 <code>close。只读通道()传入函数后,编译器直接拒绝调用 <code>close,报错 cannot close receive-only channel。
-
make(chan int)→ 可close make(chan → 可 <code>closemake( → 编译失败,无法调用 <code>close- 函数参数声明为
ch → 即使底层是双向通道,也无法在该作用域调用 <code>close
close 后继续发送会 panic,但接收仍安全
调用 close(ch) 后,任何对 ch 的发送操作(ch )都会立即触发 <code>panic: send on closed channel。而接收行为不受影响:已缓冲的数据照常取出,取完后返回零值 + false(多值接收)或阻塞解除 + 零值(单值接收)。
在 Golang 中使用 samber/hot 进行内存缓存,支持 LRU、LFU、TinyLFU、W‑TinyLFU、S3FIFO、ARC、TwoQueue、SIEVE、FIFO 等淘汰算法,提供 TTL、缓存加载器及分片功能。
- 缓冲通道
ch := make(chan int, 2),写入 2 个值后close(ch),后续仍可取两次,第三次开始返回 <code>0, false - 无缓冲通道关闭后,
立即返回零值 + <code>false(若无人在发) - 错误写法:
go func() { for i := range data { ch —— <code>range本身不阻塞,close会在循环结束后执行,但若data是无缓冲通道且无人接收,for range会卡住,close永远不执行
重复关闭或关闭 nil 通道必然 panic
close(nilChan) 和 close(alreadyClosedCh) 都在运行时触发 panic,且无法 recover。这不是逻辑错误,是 Go 运行时的硬性检查。
- 常见误判:
if ch != nil { close(ch) }不能防住重复关闭,需额外状态控制 - 并发场景下多个 goroutine 都可能走到
close,必须用sync.Once或原子布尔标志(如atomic.CompareAndSwapUint32(&closed, 0, 1))确保只执行一次 - nil 通道常出现在未初始化的字段或函数参数默认值中,例如
var ch chan int直接传入并调用close(ch)→panic: close of nil channel
接收方如何可靠感知关闭状态
接收方不能依赖“读到零值”判断是否关闭——因为零值可能是合法数据。唯一可靠方式是使用多值接收语法 v, ok := ,其中 <code>ok == false 表示通道已关闭且无剩余数据。
-
for v := range ch是最简写法,它隐式使用ok判断,通道关闭后自动退出循环 - 但注意:
range不会“中断”正在接收的过程;若通道有缓冲,它会读完所有已存数据才退出 - 错误模式:
for { v := —— 若发送方已 <code>close,此循环会无限接收零值,无法退出 - 更健壮的显式写法:
for { if v, ok :=
真正容易出问题的不是语法记不住,而是谁关、何时关、对方怎么响应这三件事没对齐。比如用 sync.WaitGroup 等待所有发送完成,却忘了 Wait() 后再 close;或者把 close 放在 select 的 default 分支里,导致提前关闭。这些细节一漏,轻则数据丢失,重则死锁或 panic。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










