
go 中的通道赋值(如 ch = ch1)本质上是引用值的复制——因为 channel 是 go 内置的引用类型,其变量本身存储的是指向底层通道结构(包含队列、锁、等待者列表等)的指针。该赋值不触发深拷贝,也不复制缓冲区数据或 goroutine 状态,仅将 ch1 所持有的引用地址写入 ch 变量中。
在您提供的筛法示例中:
ch1 := make(chan int) go Filter(ch, ch1, prime) ch = ch1 // 关键赋值:ch 现在指向新创建的通道 ch1
这一行使 ch “切换”到下游新通道,从而形成链式管道:前一个 Filter 的输出通道成为下一个 Filter 的输入通道。整个过程高效且无内存开销——因为所有通道变量都只是轻量级句柄。
⚠️ 注意事项:
- 非线程安全的变量重赋值:虽然通道本身是并发安全的(读/写操作原子),但多个 goroutine 同时对同一通道变量(如 ch)执行 ch = ch1 可能引发竞态。您的主 goroutine 单独执行该赋值,因此安全;若需多 goroutine 协同更新通道引用,请配合 sync.Mutex 或使用 channel 本身传递新通道(更符合 Go 风格)。
- 生命周期管理:被替换的旧通道(如原 ch)若仍有 goroutine 在读/写,不会立即销毁;Go 运行时通过引用计数自动回收完全无人引用的通道及其资源。
- 与其它引用类型一致:channel 的赋值行为与 slice、map、*T 完全相同——均复制描述符(header),而非底层数组、哈希表或结构体。
总结:ch = ch1 是零成本的引用重绑定,是构建动态管道、实现 CSP 模式(如素数筛)的关键基础。理解其引用本质,有助于写出高效、清晰且符合 Go 并发哲学的代码。










