go并发三大核心模式是生产者-消费者、扇出/扇入、管道:前者实现任务分发与协作,后者分别支持并行处理与结果聚合,管道则完成多阶段数据流的模块化编排。

Go 语言的并发模型以 goroutine 和 channel 为核心,生产者-消费者、扇出(fan-out)与扇入(fan-in)、管道(pipeline)这三种模式是构建可伸缩、解耦、易维护并发程序的基础范式。它们不是孤立技巧,而是层层递进的设计思想:从任务分发与协作,到并行处理与结果聚合,再到多阶段数据流编排。
生产者-消费者:用 channel 协调协作关系
这是最基础的并发解耦模式。生产者生成数据写入 channel,消费者从 channel 读取并处理,二者通过 channel 同步、缓冲和限流,无需共享内存或显式锁。
关键点:
- channel 类型决定数据流向:无缓冲 channel 实现同步通信;有缓冲 channel 缓解速度差异,但需注意容量设置(避免内存积压或过早阻塞)
- 生产者应关闭 channel 表明“不再发送”,消费者用
for range ch安全接收全部数据 - 多个消费者可同时从同一 channel 读取(竞争式消费),适合任务分发场景;若需顺序消费,保持单个消费者即可
示例中常见错误是生产者未关闭 channel 导致消费者永久阻塞,或消费者未检查读取是否成功(如用 val, ok := 判断 channel 是否已关闭)。
立即学习“go语言免费学习笔记(深入)”;
扇出与扇入:提升吞吐与聚合结果
扇出(fan-out)指将一个输入源分发给多个 goroutine 并行处理;扇入(fan-in)指将多个输出 channel 合并为一个 channel,供下游统一消费。两者常配合使用,实现“并行处理 + 串行汇总”。
典型做法:
- 扇出:启动 N 个 goroutine,每个从同一输入 channel 读取任务(如
for job := range in),各自处理后写入自己的结果 channel - 扇入:用一个函数(如
merge(chs ...)启动 goroutine 分别从各结果 channel 读取,并将数据转发到一个公共输出 channel;也可用 <code>select配合default实现非阻塞合并(适用于实时性要求高的场景)
注意:扇入时若某 goroutine 处理慢或 panic,可能导致其 channel 被阻塞,影响整体合并进度。建议配合 context 控制超时,或对每个 worker 加 recover。
管道设计:组合多阶段处理流
管道是函数式并发风格的体现:每个阶段是一个独立的 goroutine 函数,接收输入 channel,返回输出 channel,阶段间用 channel 连接。整个数据流像 Unix 管道一样可组合、可测试、可替换。
设计要点:
- 每个阶段只做一件事(单一职责),例如:读取 → 解析 → 过滤 → 转换 → 存储
- 阶段之间用无缓冲或小缓冲 channel 连接,避免中间数据堆积;必要时在瓶颈阶段前加缓冲
- 支持取消与错误传播:用
context.Context传递取消信号,错误可通过额外 error channel 返回,或封装进结构体随数据流传递
例如:readFiles(ctx) → parseLines(ctx, in) → filterValid(ctx, in) → countWords(ctx, in),任意阶段可被替换或跳过,不影响其余流程。
这三种模式本质是 channel 编排的不同粒度:生产者-消费者解决一对多协作;扇出扇入解决并行化与结果收敛;管道解决复杂流程的模块化组装。熟练掌握它们,就能写出清晰、健壮、易于演化的 Go 并发程序。










