Application Scenarios

应用场景:这个知识点实际用在哪里

Channel 不是为了替代所有共享内存,而是用来表达 goroutine 之间的数据交接、任务排队和完成信号。面试时要能说出:什么场景需要无缓冲,什么场景更适合有缓冲。

01

Worker Pool 任务队列

业务例子
HTTP 请求进入后台任务系统后,把图片处理、批量计算、消息发送等任务写入 jobs channel,由固定数量的 worker goroutine 消费。
为什么适合
有缓冲 Channel 可以暂存短时间突发任务,同时 worker 数量限制了真实并发度,天然形成一个有限队列。
注意
缓冲区不能无限放大。长期生产速度大于消费速度时,应该限流、拒绝、降级或扩容消费者,而不是只加大 cap。
02

goroutine 完成通知

业务例子
主 goroutine 启动一个后台计算,希望等它完成后再继续,例如生成文件后再返回下载地址。
为什么适合
无缓冲 Channel 或容量为 1 的 done Channel 能明确表达‘任务完成’这个同步事件,比轮询一个布尔变量更清晰。
注意
如果只是等待一组 goroutine 全部完成,sync.WaitGroup 往往比为每个任务单独建 Channel 更直接。
03

流水线 Pipeline

业务例子
读取数据 → 校验 → 转换 → 持久化,每个阶段都是独立 goroutine,上一阶段通过 Channel 把结果交给下一阶段。
为什么适合
Channel 把阶段之间的数据流显式化,阶段可以独立扩容,并通过阻塞形成背压,避免上游无限快地产生数据。
注意
必须设计退出机制。某个阶段提前返回但上游仍继续发送,很容易造成 goroutine 泄漏。
04

Fan-out / Fan-in 并发处理

业务例子
一个商品列表拆给多个 goroutine 并发调用远程接口,再通过 results channel 汇总所有结果。
为什么适合
Channel 适合把任务分发给多个消费者,再把结果汇聚到一个消费者,代码比共享 slice + 多把锁更容易表达数据流。
注意
多发送者场景下不要由任意 worker 随意 close(results),通常由 WaitGroup 协调后统一关闭。

什么时候不应该硬用

  • 只是保护一个共享计数器或一个很小的临界区时,优先考虑 atomic 或 Mutex,不要为了‘Go 风格’强行套 Channel。
  • 需要随机访问、频繁读取同一份共享状态时,Channel 往往不如直接受锁保护的数据结构自然。
  • 需要无界消息堆积时不要依赖超大 buffered Channel;这通常意味着需要真正的 MQ、持久化队列或流控策略。
面试里可以这样落地

例如我做一个批处理 Worker Pool,会创建有缓冲 jobs Channel 做有限任务队列,用固定数量 goroutine 消费;如果是必须确认接收方已经接手的同步信号,我会选无缓冲 Channel。Channel 的选择本质看是否需要同步交接,以及是否允许生产者和消费者存在短暂速度差。