Go 并发三板斧:如何优雅地收集多个 goroutine 的结果?

发布时间:2026/9/13 22:31:30

Go 并发三板斧:如何优雅地收集多个 goroutine 的结果? ### 写在前面在 Go 里写并发程序最常见的一个需求是**同时发起多个任务然后收集它们的结果。**但收集的方式不止一种。你是**全部等齐再处理**还是**谁先回来用谁的**还是**边回来边处理**这三种场景对应了 Go 并发编程里三种不同的模式。这篇文章带你一次性搞清楚。---## 场景设定假设我们有一个酒店后台系统需要同时查询三个数据源- 房价fetchPrice- 房态fetchRoomStatus- 客户偏好fetchPreference每个查询耗时 1-3 秒不等我们希望能用并发的方式加速。gotype QueryResult struct {Price stringRoom stringPrefer stringErr error}---## 模式一全部等齐再处理sync.WaitGroup这是最经典的用法**等所有任务都完成再统一返回。**gofunc queryAll(ctx context.Context, room string) QueryResult {var wg sync.WaitGroupvar mu sync.Mutexresult : QueryResult{}wg.Add(3)go func() {defer wg.Done()price, err : fetchPrice(ctx, room)mu.Lock()result.Price priceresult.Err errmu.Unlock()}()go func() {defer wg.Done()roomStatus, err : fetchRoomStatus(ctx, room)mu.Lock()result.Room roomStatusif err ! nil {result.Err err}mu.Unlock()}()go func() {defer wg.Done()prefer, err : fetchPreference(ctx, room)mu.Lock()result.Prefer preferif err ! nil {result.Err err}mu.Unlock()}()wg.Wait()return result}**特点**- 三个任务全部完成后wg.Wait() 才放行- 总耗时 最慢的那个任务- 适合需要完整数据的场景如生成报表、页面渲染---## 模式二谁先完成用谁的一次 select如果你只关心最快的那个结果可以用 select 取第一个回来的数据。gofunc queryAny(ctx context.Context, room string) QueryResult {ch : make(chan QueryResult, 3)go func() {price, err : fetchPrice(ctx, room)ch - QueryResult{Price: price, Err: err}}()go func() {roomStatus, err : fetchRoomStatus(ctx, room)ch - QueryResult{Room: roomStatus, Err: err}}()go func() {prefer, err : fetchPreference(ctx, room)ch - QueryResult{Prefer: prefer, Err: err}}()select {case result : -ch:return resultcase -ctx.Done():return QueryResult{Err: ctx.Err()}}}**特点**- 只取第一个返回的结果其余忽略- 总耗时 最快的那个任务- 适合竞争式查询如查多个缓存、多个供应商报价---## 模式三边完成边收集循环 select如果你既要**全部结果**又想**边完成边处理**可以用 for select 循环。gofunc queryAllWithSelect(ctx context.Context, room string) QueryResult {ch : make(chan QueryResult, 3)go func() {price, err : fetchPrice(ctx, room)ch - QueryResult{Price: price, Err: err}}()go func() {roomStatus, err : fetchRoomStatus(ctx, room)ch - QueryResult{Room: roomStatus, Err: err}}()go func() {prefer, err : fetchPreference(ctx, room)ch - QueryResult{Prefer: prefer, Err: err}}()result : QueryResult{}for i : 0; i 3; i {select {case part : -ch:if part.Price ! {result.Price part.Price}if part.Room ! {result.Room part.Room}if part.Prefer ! {result.Prefer part.Prefer}if part.Err ! nil result.Err nil {result.Err part.Err}case -ctx.Done():result.Err ctx.Err()return result}}return result}**特点**- 所有结果都能收到- 可以边收边处理如实时更新 UI 进度条- 总耗时 最慢的那个任务但不会卡死有超时保护---## 三种模式对比一览| 模式 | 工具 | 结果完整性 | 总耗时 | 适用场景 || :--- | :--- | :--- | :--- | :--- || 全部等齐 | sync.WaitGroup | ✅ 全部 | 最慢的任务 | 报表、完整页面 || 取最快 | 一次 select | ❌ 一个 | 最快的任务 | 缓存竞争、降级 || 边收边等 | 循环 select | ✅ 全部 | 最慢的任务 | 进度展示、实时更新 |---## 总结Go 的并发模型并不复杂但“收集结果”这个看似简单的需求其实有几种不同的实现方式。**选择哪个取决于你的业务需求**- 需要全部数据 用 WaitGroup- 只要最快的那一个 用 select- 全部都要还要实时反馈 用循环 select这三种模式你学会了吗
延伸阅读

更多相关文章

2026/9/14 11:03:06

xAI开源Grok Build:Rust终端编程智能体架构全解与实战指南

xAI开源Grok Build:Rust终端编程智能体架构全解与实战指南 2026年7月15日,埃隆马斯克旗下人工智能公司xAI做了一件让整个开发者社区始料未及的事:将其核心工程工具Grok Build的完整源代码开源至GitHub。这是xAI自2023年成立以来首次对外公开核…

2026/9/10 13:17:40

J1900软路由折腾记:用ESXi 6.7虚拟化OpenWrt,搞定不支持直通的网卡配置

J1900软路由虚拟化实战:ESXi 6.7下非直通网卡的OpenWrt部署方案 当手头的J1900工控机遇上不支持VT-d的硬件限制,如何实现多网口软路由的完美虚拟化?这个困扰许多老旧硬件玩家的技术难题,其实可以通过ESXi的虚拟网络架构巧妙解决。不同于常规的直通方案,我们将深入探索虚拟…

2026/9/14 18:55:19

水质监测管理平台:水质实时监测・化验记录全链路业务建模

前言水质监测管理,是守护供水安全的最后一道防线,覆盖在线水质数据自动采集、实时监测、国标限值比对、超标分级预警、异常处置复核,以及实验室采样、化验、审核、归档全流程,业务对标国家标准、时效要求高、处置复核需双人把关、…

2026/9/14 18:55:19

守护万家数字安全感,网络安全走进社区 “家门口”

引言:立足网安周 “进社区”,找准基层网络安全治理切口2026 年国家网络安全宣传周于 9 月 14‑20 日在全国开展,主题为“网络安全为人民,网络安全靠人民 —— 智能时代 网安护航”。宣传周持续推进网络安全 “七进” 活动&#xf…

2026/9/14 18:55:19

DPR适配实战:解决移动端图片模糊的根本方案

1. 这不是图片质量的问题,是设备与渲染的“语言错位” 你肯定遇到过:设计师发来的 PNG 稿子在 Sketch 里放大看连像素点都锐利得能数清,导出切图后塞进前端页面,一上真机——尤其是 iPhone 14 Pro 或华为 Mate 50——图片立刻像蒙…

2026/9/14 18:55:19

氛围编程与职场效能:开发者如何平衡创新与绩效

1. 项目背景解析:当"氛围编程"遭遇职场现实"氛围编程"这个概念最近在技术社区引发了不少讨论,它描述的是一种更注重工作环境舒适度和团队协作体验的编程方式。典型的氛围编程实践包括:开放式协作空间设计弹性工作时间制度…

2026/9/14 2:17:50

拯救者Y7000黑屏故障排查与维修实战指南

1. 项目概述:一台黑屏的拯救者Y7000,到底卡在哪一步? 联想拯救者Y7000系列笔记本,从2018年第一代搭载i5-8300H开始,到后来的i7-9750H、i7-10750H、i5-11400H,再到2023年款的R7-7840HS,它始终是学…

2026/9/14 0:03:22

KCF目标跟踪算法与OTB工程实现:毕业设计实战解析

简介:这是一份基于KCF核相关滤波算法、融合尺度池与抗遮挡处理的目标检测跟踪MATLAB完整源码,主要面向计算机相关专业准备毕业设计、课程设计或期末大作业的学生,也适合需要项目实战练习的初学者。源码在OTB数据集上完成验证,能够…

2026/9/14 0:03:22

语音情感识别实战:Keras实现LSTM、CNN、SVM与MLP多模型对比

简介:面向语音情感识别入门与进阶开发者,这份基于Keras的项目源码完整实现了LSTM、CNN、SVM、MLP四种模型,兼容Python3.8与Keras/TensorFlow2环境。压缩包内含49个文件,大小约70.31MB,主体包括Python脚本、yaml/json配…

2026/9/14 11:59:31

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/14 13:53:59

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/14 11:22:57

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码