<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Shuai&apos;s Blog</title><description>写点代码，想点事情</description><link>https://blog.shuaiguoer.com/</link><templateTheme>Firefly</templateTheme><templateThemeVersion>6.5.8</templateThemeVersion><templateThemeUrl>https://github.com/CuteLeaf/Firefly</templateThemeUrl><lastBuildDate>2026年3月11日 17:21:23</lastBuildDate><item><title>MySQL连接池配置指南：别让数据库被你的&quot;慷慨&quot;压垮</title><link>https://blog.shuaiguoer.com/posts/mysql-connection-pool/</link><guid isPermaLink="true">https://blog.shuaiguoer.com/posts/mysql-connection-pool/</guid><description>把MySQL连接池调好，本质上是在做一件事：在数据库可承受范围内，用最少的连接，稳定地服务住高峰并发。这不是玄学，是一组可以推理的工程权衡。</description><pubDate>Sat, 07 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;把 MySQL 连接池调好，本质上是在做一件事：&lt;strong&gt;在数据库可承受范围内，用最少的连接，稳定地服务住高峰并发&lt;/strong&gt;。这不是玄学，是一组可以推理的工程权衡。&lt;/p&gt;
&lt;section&gt;&lt;h2&gt;一句话核心观点&lt;a href=&quot;#一句话核心观点&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;连接不是越多越好&lt;/strong&gt;，连接是”共享的稀缺资源”，不是”免费的并发开关”&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;连接池的目标不是”抗住所有请求”&lt;/strong&gt;，而是”把压力挡在应用层”&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;一、你在给谁配？先想清楚这三个对象&lt;a href=&quot;#一你在给谁配先想清楚这三个对象&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;配置连接池前，必须同时看三方：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;MySQL 本身&lt;/strong&gt; —— 它的承受能力是天花板&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;单个应用实例&lt;/strong&gt; —— 它的 CPU 核数决定了真实并发能力&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;整个应用集群&lt;/strong&gt; —— 实例数乘以单实例连接数，才是 MySQL 真正面对的压力&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;很多事故的根源在于：👉 单实例看着没问题，集群一扩容，MySQL 直接被连接数打爆。就像一个人能扛 50 斤，你让 10 个人同时往他身上扔 50 斤，他肯定扛不住。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;二、MySQL 侧的硬约束（地心引力）&lt;a href=&quot;#二mysql-侧的硬约束地心引力&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;1. max_connections 是硬天花板&lt;a href=&quot;#1-max_connections-是硬天花板&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这是 MySQL 能同时处理的最大连接数。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;经验值判断：&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;每个连接 ≈ 2–10 MB 内存（取决于配置）&lt;/li&gt;
&lt;li&gt;连接越多，上下文切换、锁竞争、buffer 抖动越严重&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;现实结论：&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;MySQL 通常在 &lt;strong&gt;200–500 个活跃连接&lt;/strong&gt; 内效率最高&lt;/li&gt;
&lt;li&gt;上千连接还能活，但性能开始退化&lt;/li&gt;
&lt;li&gt;连接池不能突破这个上限，只能更聪明地使用它&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;2. MySQL 不擅长”超高并发短查询”&lt;a href=&quot;#2-mysql-不擅长超高并发短查询&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;MySQL 更像一个 &lt;strong&gt;老派工匠&lt;/strong&gt;：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;喜欢少量连接，每个连接跑得久一点&lt;/li&gt;
&lt;li&gt;批量、顺序、可预测的工作方式&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;它 &lt;strong&gt;不擅长&lt;/strong&gt;：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;上千连接同时抢 CPU&lt;/li&gt;
&lt;li&gt;大量连接在”连 / 查 / 断”之间频繁抖动&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;这决定了：&lt;strong&gt;连接池要”限流”，不是”放水”&lt;/strong&gt;。就像给老工匠安排工作，不能让他同时接 100 个急单，他会崩溃的。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;三、应用侧：一个实例该开多少连接？&lt;a href=&quot;#三应用侧一个实例该开多少连接&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这是最关键、也是最容易配错的地方。&lt;/p&gt;&lt;section&gt;&lt;h3&gt;1. 先看你的应用模型&lt;a href=&quot;#1-先看你的应用模型&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;问自己三个问题：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;是不是 IO 密集型？
&lt;ul&gt;
&lt;li&gt;普通 Web / API 服务：是&lt;/li&gt;
&lt;li&gt;大量 CPU 计算：不是&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;单个请求会不会串行访问 DB 多次？
&lt;ul&gt;
&lt;li&gt;是 → 更需要连接余量&lt;/li&gt;
&lt;li&gt;否 → 连接数可以更小&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;DB 查询耗时大概多少？
&lt;ul&gt;
&lt;li&gt;5–10ms：连接用得快&lt;/li&gt;
&lt;li&gt;100ms+：连接会被占住&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;2. 一个非常实用的估算公式（工程经验）&lt;a href=&quot;#2-一个非常实用的估算公式工程经验&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;单实例最大连接数 ≈ CPU 核数 × 2 ~ 4&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;例如：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;4 核 → 8 ~ 16&lt;/li&gt;
&lt;li&gt;8 核 → 16 ~ 32&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;理由很朴素：同一时刻真正能跑 SQL 的线程 ≈ CPU 核数，多出来的连接只是在排队或制造切换成本。就像一个 4 核 CPU 的厨房，最多 4 个厨师能同时炒菜，再多的人只能排队等锅。&lt;/p&gt;&lt;p&gt;如果你发现：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;CPU 没满&lt;/li&gt;
&lt;li&gt;连接却经常打满&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;那不是连接池太小，是 &lt;strong&gt;SQL 慢、事务太长或索引有问题&lt;/strong&gt;。这时候加连接就像给堵车的高速公路加车道，治标不治本。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;3. 不要把”并发数”直接映射成”连接数”&lt;a href=&quot;#3-不要把并发数直接映射成连接数&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这是经典误区：“我 QPS 很高 / 并发很大，所以我需要很多连接”。&lt;/p&gt;&lt;p&gt;错。连接池靠的是 &lt;strong&gt;复用&lt;/strong&gt;，不是一一对应。真正的关系是：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;连接数 ≈ 并发请求数 × 单次 DB 占用时间&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;缩短 SQL 时间，比加连接有效得多。就像餐厅翻台率提高了，同样的桌子能服务更多客人，不需要加桌子。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;四、集群视角：真正容易翻车的地方&lt;a href=&quot;#四集群视角真正容易翻车的地方&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;假设：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;MySQL max_connections = 500&lt;/li&gt;
&lt;li&gt;你有 10 个应用实例&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;如果你给每个实例配：&lt;code&gt;maxOpenConns = 100&lt;/code&gt;&lt;/p&gt;&lt;p&gt;那么上线那一刻，MySQL 理论最大连接数是：&lt;code&gt;10 × 100 = 1000&lt;/code&gt; ❌&lt;/p&gt;&lt;p&gt;数据库会先死给你看。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;正确做法是反推：&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;单实例最大连接数 ≤ max_connections / 实例数 × 安全系数&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;例如：&lt;code&gt;500 / 10 × 0.7 ≈ 35&lt;/code&gt;&lt;/p&gt;&lt;p&gt;这比”拍脑袋 100”安全得多。就像给 10 个人分蛋糕，不能每个人都想拿最大的一块，得先看看蛋糕有多大。&lt;/p&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;五、连接池三个核心参数详解&lt;a href=&quot;#五连接池三个核心参数详解&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;以 Go 的 &lt;code&gt;database/sql&lt;/code&gt; 为例（思想对其他语言通用）：&lt;/p&gt;&lt;section&gt;&lt;h3&gt;1. MaxOpenConns —— 连接池的”硬天花板”&lt;a href=&quot;#1-maxopenconns--连接池的硬天花板&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这是 &lt;strong&gt;硬上限&lt;/strong&gt;：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;平时不一定用满&lt;/li&gt;
&lt;li&gt;用满说明你已经在排队&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;作用机制：&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;第 1 个请求来 → 建立第 1 个连接&lt;/li&gt;
&lt;li&gt;…&lt;/li&gt;
&lt;li&gt;第 8 个请求来 → 建立第 8 个连接&lt;/li&gt;
&lt;li&gt;第 9 个请求来 → 不能再建连接了，只能等&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;MaxOpenConns 是限流器，不是性能开关&lt;/strong&gt;。它保证：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;MySQL 不会被瞬间打爆&lt;/li&gt;
&lt;li&gt;慢 SQL 不会无限扩散&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;建议：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;小而克制&lt;/li&gt;
&lt;li&gt;和实例数联动计算&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;2. MaxIdleConns —— 连接的”保温箱”&lt;a href=&quot;#2-maxidleconns--连接的保温箱&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;作用：&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;减少频繁建连&lt;/li&gt;
&lt;li&gt;但空闲连接也占资源&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;工作原理：&lt;/strong&gt;
高峰过后，8 个连接被归还给连接池。连接池最多只留 4 个空闲连接，多余的 4 个会被立刻关闭。&lt;/p&gt;&lt;p&gt;为什么不全留？因为：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;空闲连接 ≠ 免费&lt;/li&gt;
&lt;li&gt;每个连接占内存、线程、buffer&lt;/li&gt;
&lt;li&gt;长期空闲连接更容易”悄悄失效”&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;MaxIdleConns 决定的是”平时我背多少连接成本”。就像保温箱，太大浪费电，太小饭菜凉得快。&lt;/p&gt;&lt;p&gt;经验值：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;等于或略小于 MaxOpenConns&lt;/li&gt;
&lt;li&gt;对延迟敏感服务可以偏大&lt;/li&gt;
&lt;li&gt;对 DB 压力大的系统可以偏小&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;3. ConnMaxLifetime —— 连接的”寿命上限”&lt;a href=&quot;#3-connmaxlifetime--连接的寿命上限&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;作用：&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;避免 MySQL / NAT / LB 偷偷断连接&lt;/li&gt;
&lt;li&gt;让连接的内存状态周期性归零&lt;/li&gt;
&lt;li&gt;减少”跑几天就慢”的玄学问题&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;工作原理：&lt;/strong&gt;
某个连接已经存在了 6 分钟，即使它现在很健康，下次它被归还到连接池时，连接池发现：你活太久了。它会被关闭，下次再需要时，新建一个。&lt;/p&gt;&lt;p&gt;这解决的是三类慢性问题：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;MySQL / LB / 防火墙中途断链&lt;/li&gt;
&lt;li&gt;连接内存状态长期膨胀&lt;/li&gt;
&lt;li&gt;运行几天后开始”莫名其妙变慢”&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;它不是为了性能，是为了 &lt;strong&gt;长期稳定性&lt;/strong&gt;。就像人需要定期体检，连接也需要定期”换血”。&lt;/p&gt;&lt;p&gt;建议：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;1–5 分钟一个量级&lt;/li&gt;
&lt;li&gt;一定要 &lt;strong&gt;小于 MySQL 的 wait_timeout&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;4. 把三者放在同一条时间线上&lt;a href=&quot;#4-把三者放在同一条时间线上&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;可以把一个连接的一生画成这样：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[ 创建 ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;↓&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[ 被请求使用 ] ←—— 多次&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;↓&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[ 归还池中（Idle） ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;↓&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[ 超过 MaxIdleConns？] —— 是 → [ 立即关闭 ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;↓ 否&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[ 超过 ConnMaxLifetime？] —— 是 → [ 关闭 ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;   &lt;/span&gt;&lt;/span&gt;&lt;span&gt;↓ 否&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;[ 等待下一次使用 ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;而 MaxOpenConns 始终在旁边盯着：“我最多允许同时存在 8 个你们。“&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;5. 三个参数的”分工关系”&lt;a href=&quot;#5-三个参数的分工关系&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;一句话总结它们的角色：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MaxOpenConns&lt;/strong&gt; 👉 控制”最多能有多少连接活着”（安全阀）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MaxIdleConns&lt;/strong&gt; 👉 控制”高峰过后留多少备用连接”（成本 / 延迟平衡）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ConnMaxLifetime&lt;/strong&gt; 👉 控制”单个连接活多久”（长期健康）&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;它们解决的是 &lt;strong&gt;完全不同维度的问题&lt;/strong&gt;，不能互相替代。就像人体的免疫系统、消化系统、神经系统，各司其职，缺一不可。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;6. 配置不当的后果&lt;a href=&quot;#6-配置不当的后果&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;section&gt;&lt;h4&gt;只调 MaxOpenConns，会怎样？&lt;a href=&quot;#只调-maxopenconns会怎样&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;高峰时能顶住，但连接可能：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;永久不释放&lt;/li&gt;
&lt;li&gt;内存膨胀&lt;/li&gt;
&lt;li&gt;被中间设备掐死&lt;/li&gt;
&lt;li&gt;系统跑几天就开始抽风&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;就像只顾着招人，不管人员流动，最后公司里全是老员工，效率低下。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;Idle 配太大，会怎样？&lt;a href=&quot;#idle-配太大会怎样&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;ul&gt;
&lt;li&gt;MySQL 长期背着大量空闲连接&lt;/li&gt;
&lt;li&gt;新实例上线瞬间连满&lt;/li&gt;
&lt;li&gt;运维看着一堆 Sleep 连接发愁&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;就像餐厅里空桌子太多，占着地方不赚钱。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;不设 ConnMaxLifetime，会怎样？&lt;a href=&quot;#不设-connmaxlifetime会怎样&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;系统一开始很稳，几天后：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;偶发 “bad connection”&lt;/li&gt;
&lt;li&gt;性能抖动&lt;/li&gt;
&lt;li&gt;重启服务后神奇恢复&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;这是经典症状。就像一个人长期不体检，突然有一天倒下了。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;最后一句工程真相&lt;a href=&quot;#最后一句工程真相&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;&lt;strong&gt;连接池不是”多快”的工具，是”别死”的工具。&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;这三个参数一起，做的是同一件事：让数据库连接像新陈代谢一样——有上限、有休息、有淘汰。&lt;/p&gt;&lt;p&gt;理解成”生态系统”，而不是”数字开关”，你就很难配错了。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;六、通用公式：一条能直接上线的经验法则&lt;a href=&quot;#六通用公式一条能直接上线的经验法则&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;好，这里给你一个 &lt;strong&gt;真的能用、而且不容易被滥用的”通用公式”&lt;/strong&gt;。它不是数学定律，是工程学里的”安全近似”，在 &lt;strong&gt;大多数业务、尤其是后台 / API 服务&lt;/strong&gt; 里都站得住。&lt;/p&gt;&lt;section&gt;&lt;h3&gt;通用结论版（先记住这一行）&lt;a href=&quot;#通用结论版先记住这一行&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;单实例 MySQL 最大连接数 ≈ min( CPU 核数 × 4 , 32 )&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;然后配套三条铁律：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;MaxIdleConns ≈ MaxOpenConns ÷ 2&lt;/li&gt;
&lt;li&gt;ConnMaxLifetime = 1 ~ 10 分钟&lt;/li&gt;
&lt;li&gt;集群总连接数 ≤ MySQL max_connections × 70%&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;这四条合起来，基本不会出事。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;为什么这个公式”稳”&lt;a href=&quot;#为什么这个公式稳&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;section&gt;&lt;h4&gt;1️⃣ CPU × 4 是现实上限，不是理论极限&lt;a href=&quot;#1️⃣-cpu--4-是现实上限不是理论极限&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;同一时刻：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;真正执行 SQL 的线程 ≈ CPU 核数&lt;/li&gt;
&lt;li&gt;多出来的连接只是在等待锁、IO 或调度&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;×4 已经是：IO 等待、网络抖动、偶发慢查询全部算进去后的 &lt;strong&gt;宽松冗余&lt;/strong&gt;。超过这个数，收益快速递减。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;2️⃣ 32 是经验性的”自保上限”&lt;a href=&quot;#2️⃣-32-是经验性的自保上限&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;不管你 16 核还是 64 核：后端服务极少需要 &amp;gt;32 个 DB 连接。超过 32，问题往往不在”连接不够”。&lt;/p&gt;&lt;p&gt;这是防止”硬件很好 → 连接无限膨胀”的刹车片。就像给跑车装限速器，不是为了让你开不快，而是为了让你别开太快。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;3️⃣ Idle 连接不是越多越好&lt;a href=&quot;#3️⃣-idle-连接不是越多越好&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;Idle ≈ Open / 2 的含义是：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;足够应对突发请求&lt;/li&gt;
&lt;li&gt;又不会让 DB 长期背着无用连接&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;对连接重建成本和资源占用取得平衡。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;4️⃣ 生命周期不是性能参数，是健康参数&lt;a href=&quot;#4️⃣-生命周期不是性能参数是健康参数&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;ConnMaxLifetime 的作用不是快，而是 &lt;strong&gt;防老化&lt;/strong&gt;：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;避免 MySQL / NAT / LB 偷偷断连接&lt;/li&gt;
&lt;li&gt;让连接的内存状态周期性归零&lt;/li&gt;
&lt;li&gt;减少”跑几天就慢”的玄学问题&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;把公式翻译成一句人话&lt;a href=&quot;#把公式翻译成一句人话&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;“每个应用实例，用 CPU 能真实跑得动的连接数，再乘一点容错；所有实例加起来，永远别把 MySQL 撑满。“&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;一个完整的例子&lt;a href=&quot;#一个完整的例子&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;应用实例：8 核&lt;/li&gt;
&lt;li&gt;MySQL：max_connections = 500&lt;/li&gt;
&lt;li&gt;应用实例数：10&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;单实例：&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;MaxOpenConns = min(8 × 4, 32) = 32&lt;/li&gt;
&lt;li&gt;MaxIdleConns = 16&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;集群校验：&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;10 × 32 = 320 &amp;lt; 500 × 0.7 = 350 ✅&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;这是一个 &lt;strong&gt;工程上舒服&lt;/strong&gt; 的状态。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;什么时候这个公式不适用？&lt;a href=&quot;#什么时候这个公式不适用&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;你可以当成”警告灯”：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;超高并发 OLTP（支付、撮合）&lt;/li&gt;
&lt;li&gt;大量慢查询 / 报表&lt;/li&gt;
&lt;li&gt;长事务（秒级）&lt;/li&gt;
&lt;li&gt;单请求多次串行 DB 访问&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;这时该做的是：拆查询、上只读实例、异步化、分库分表，而不是把 MaxOpenConns 往上拉。&lt;/p&gt;&lt;p&gt;最后一句压箱底的话：&lt;strong&gt;连接池的正确目标不是”把并发顶住”，而是”把数据库保护住”&lt;/strong&gt;。这个公式做的正是这件事。在大多数系统里，它不是最激进的，但几乎总是最安全的。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;七、实战案例：200人后台管理系统怎么配？&lt;a href=&quot;#七实战案例200人后台管理系统怎么配&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;对一个 &lt;strong&gt;最多 200 人使用的后台管理系统&lt;/strong&gt;（典型：CRUD、多列表、偶发导出），&lt;strong&gt;单 MySQL 实例 + 单应用实例&lt;/strong&gt; 时：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;MaxOpenConns：5 ~ 10&lt;/li&gt;
&lt;li&gt;MaxIdleConns：2 ~ 5&lt;/li&gt;
&lt;li&gt;ConnMaxLifetime：5 ~ 10 分钟&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;如果是 &lt;strong&gt;2–3 个应用实例&lt;/strong&gt;：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;MaxOpenConns：3 ~ 6 / 实例&lt;/li&gt;
&lt;li&gt;MaxIdleConns：1 ~ 3 / 实例&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;是的，看起来非常小，这是 &lt;strong&gt;刻意的&lt;/strong&gt;。&lt;/p&gt;&lt;section&gt;&lt;h3&gt;为什么 200 人 ≠ 200 个连接&lt;a href=&quot;#为什么-200-人--200-个连接&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;这是后台系统最容易被高估的地方。&lt;/p&gt;&lt;section&gt;&lt;h4&gt;1️⃣ 200 人的真实并发极低&lt;a href=&quot;#1️⃣-200-人的真实并发极低&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;后台管理系统的现实画像是：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;同时在线：可能 50–100&lt;/li&gt;
&lt;li&gt;同时点按钮的：10–20&lt;/li&gt;
&lt;li&gt;同时打到 DB 的：5–10&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;人类不是压测工具。大部分时间在看屏幕、想事情、切页面、喝水。这意味着：&lt;strong&gt;真实 DB 并发通常 &amp;lt; 10&lt;/strong&gt;。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;2️⃣ 后台 SQL 的”占用时间”很短&lt;a href=&quot;#2️⃣-后台-sql-的占用时间很短&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;后台系统通常是：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;单表 / 少量 join&lt;/li&gt;
&lt;li&gt;强索引&lt;/li&gt;
&lt;li&gt;读多写少&lt;/li&gt;
&lt;li&gt;无长事务（如果有，那是 bug）&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;一次查询常见：5–20 ms，连接会被非常快地归还给池子。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;3️⃣ 小连接池反而更安全&lt;a href=&quot;#3️⃣-小连接池反而更安全&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;p&gt;后台系统最怕的不是”慢一点”，而是：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;某个列表页全表扫描&lt;/li&gt;
&lt;li&gt;某次导出跑了 30 秒&lt;/li&gt;
&lt;li&gt;某个误操作触发 N 次写&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;小连接池的效果是：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;问题请求被限在少量连接里&lt;/li&gt;
&lt;li&gt;其他请求还能活着&lt;/li&gt;
&lt;li&gt;MySQL 不会被瞬间压垮&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;这是”隔离”，不是”抠门”。就像防火墙，不是为了让你上网慢，而是为了让你不被烧掉。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;推荐你顺手配的 Go 示例&lt;a href=&quot;#推荐你顺手配的-go-示例&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;db&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;SetMaxOpenConns&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;8&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;db&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;SetMaxIdleConns&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;4&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;db&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;SetConnMaxLifetime&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;time&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Minute&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;这是那种：能跑一年、运维几乎感觉不到、出问题也好定位的配置。&lt;/p&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;什么时候需要调大？&lt;a href=&quot;#什么时候需要调大&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;只有在你 &lt;strong&gt;明确观测到&lt;/strong&gt;：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;连接池 wait 时间明显&lt;/li&gt;
&lt;li&gt;MySQL Threads_running 很低&lt;/li&gt;
&lt;li&gt;SQL 本身已经确认没问题&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;才考虑从 8 → 12，而不是 8 → 50。&lt;/p&gt;&lt;p&gt;最后一个略带哲学意味的事实：&lt;strong&gt;后台系统不是给”并发”用的，是给”人”用的&lt;/strong&gt;。人类的操作节奏，天然就是最好的限流器。&lt;/p&gt;&lt;/section&gt;&lt;/section&gt;
&lt;section&gt;&lt;h2&gt;八、最后的总结&lt;a href=&quot;#八最后的总结&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;连接池配置的本质，是在三个维度上做权衡：&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;性能 vs 稳定性&lt;/strong&gt;：更多连接 = 更高并发，但更不稳定&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;延迟 vs 成本&lt;/strong&gt;：更多 Idle 连接 = 更低延迟，但更高资源占用&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;短期 vs 长期&lt;/strong&gt;：长连接 = 更快启动，但可能老化失效&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;记住那个通用公式：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;单实例 MySQL 最大连接数 ≈ min( CPU 核数 × 4 , 32 )&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;MaxIdleConns ≈ MaxOpenConns ÷ 2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;ConnMaxLifetime = 1 ~ 10 分钟&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;集群总连接数 ≤ MySQL max_connections × 70%&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;这不是最激进的配置，但几乎总是最安全的。在大多数系统里，它能让你的数据库活得久一点，让你睡得安稳一点。&lt;/p&gt;&lt;p&gt;毕竟，&lt;strong&gt;连接池的正确目标不是”把并发顶住”，而是”把数据库保护住”&lt;/strong&gt;。理解这一点，你就已经超越了 90% 的开发者。&lt;/p&gt;&lt;p&gt;世界的奇妙之处在于：&lt;strong&gt;数据库看起来像一个并发系统，实际上是一个被精心约束的顺序机器&lt;/strong&gt;。理解这一点，连接池就不再是”参数调优”，而是系统设计的一部分。&lt;/p&gt;&lt;/section&gt;</content:encoded></item><item><title>Golang 并发控制：从 WaitGroup 到 errgroup 的深度实践与避坑指南</title><link>https://blog.shuaiguoer.com/posts/golang-errgroup/</link><guid isPermaLink="true">https://blog.shuaiguoer.com/posts/golang-errgroup/</guid><description>深度解析 errgroup 工作机制，对比 WaitGroup 揭示其在错误捕获、生命周期控制及并发限流方面的优势，附实战 Demo。</description><pubDate>Fri, 06 Feb 2026 00:00:00 GMT</pubDate><content:encoded>&lt;section&gt;&lt;h1&gt;Golang 并发控制：从 WaitGroup 到 errgroup 的深度实践与避坑指南&lt;a href=&quot;#golang-并发控制从-waitgroup-到-errgroup-的深度实践与避坑指南&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h1&gt;&lt;p&gt;在 Golang 的业务开发中，如果你还在用串行方式请求 A、B、C、D 四个不相关的接口，那你的程序性能可能和树懒没什么区别。今天我们聊聊如何从原始的 &lt;code&gt;WaitGroup&lt;/code&gt; 进化到现代化的 &lt;code&gt;errgroup&lt;/code&gt;，让你的并发代码从”包工头”升级为”精英主管”。&lt;/p&gt;&lt;hr /&gt;&lt;section&gt;&lt;h2&gt;1. 核心执行逻辑：一人报错，全家收工&lt;a href=&quot;#1-核心执行逻辑一人报错全家收工&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;很多同学搞不清楚 &lt;code&gt;errgroup&lt;/code&gt; 的 &lt;code&gt;cancel&lt;/code&gt; 到底是什么时候触发的。看下面这张图就秒懂了：&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;+-------------------------------------------------------+&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| Main Goroutine (g, ctx := errgroup.WithContext)       |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;+-------------------------------------------------------+&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;               &lt;/span&gt;&lt;/span&gt;&lt;span&gt;|                |                |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;g.Go(Func A)     g.Go(Func B)     g.Go(Func C)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;               &lt;/span&gt;&lt;/span&gt;&lt;span&gt;|                |                |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;               &lt;/span&gt;&lt;/span&gt;&lt;span&gt;|          [ B 报错返回 ]           |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;               &lt;/span&gt;&lt;/span&gt;&lt;span&gt;|                |                |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;               &lt;/span&gt;&lt;/span&gt;&lt;span&gt;|         自动调用 cancel()         |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;               &lt;/span&gt;&lt;/span&gt;&lt;span&gt;|&amp;lt;---------------|---------------&amp;gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[ A 感知 ctx.Done ]              [ C 感知 ctx.Done ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;[ 提前退出 ]                      [ 提前退出 ]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;               &lt;/span&gt;&lt;/span&gt;&lt;span&gt;|                |                |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;+-------------------------------------------------------+&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;| g.Wait() 立即接收到第一个非空 error 并返回              |&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;+-------------------------------------------------------+&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;显示更多&lt;/span&gt;&lt;span&gt;显示更少&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;执行流程说明：&lt;/strong&gt;&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;主 goroutine 通过 &lt;code&gt;errgroup.WithContext&lt;/code&gt; 创建 errgroup 实例和 context&lt;/li&gt;
&lt;li&gt;通过 &lt;code&gt;g.Go()&lt;/code&gt; 启动多个子 goroutine&lt;/li&gt;
&lt;li&gt;任意一个 goroutine 返回非空 error 时，自动触发 &lt;code&gt;cancel()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;其他 goroutine 通过 &lt;code&gt;ctx.Done()&lt;/code&gt; 感知取消信号并优雅退出&lt;/li&gt;
&lt;li&gt;&lt;code&gt;g.Wait()&lt;/code&gt; 返回第一个非空 error&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;strong&gt;关键点：&lt;/strong&gt; &lt;code&gt;cancel()&lt;/code&gt; 是自动调用的，你不需要手动触发。这就是 errgroup 的魔法所在——它像个贴心的管家，一旦发现有人出事，立马通知所有人撤退。&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;2. 缘起：为什么不推荐原生 WaitGroup？&lt;a href=&quot;#2-缘起为什么不推荐原生-waitgroup&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;想象一下，你负责一个”大杂烩”接口，需要同时查询：用户信息、订单记录、优惠券。&lt;/p&gt;&lt;section&gt;&lt;h3&gt;方案对比&lt;a href=&quot;#方案对比&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;






















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;方案&lt;/th&gt;&lt;th&gt;执行方式&lt;/th&gt;&lt;th&gt;耗时&lt;/th&gt;&lt;th&gt;问题&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;方案 A&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;串行执行&lt;/td&gt;&lt;td&gt;所有接口总和&lt;/td&gt;&lt;td&gt;性能极差，用户体验堪忧&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;方案 B&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;原生 WaitGroup&lt;/td&gt;&lt;td&gt;最慢接口耗时&lt;/td&gt;&lt;td&gt;错误难捕捉、生命周期失控&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;WaitGroup 的痛点&lt;a href=&quot;#waitgroup-的痛点&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;使用原生 &lt;code&gt;WaitGroup&lt;/code&gt; 时，你会遇到以下问题：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;错误难捕捉&lt;/strong&gt;：其中一个崩了，你得开 channel 费劲地接住 error，就像在暴风雨中接住一片雪花&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;生命周期失控&lt;/strong&gt;：如果 A 出错了，B 和 C 还在傻跑，浪费服务器资源，就像三个员工在办公室里加班，其实老板早就下班了&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;代码示例对比：&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// WaitGroup 的痛苦写法&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;wg&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;sync&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;WaitGroup&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;errChan&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;make&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;chan&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;wg&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Add&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;go&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;defer&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;wg&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Done&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;callA&lt;/span&gt;&lt;span&gt;(); &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;errChan&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// ... 重复 3 次&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;wg&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Wait&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;close&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;errChan&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;range&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;errChan&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// 处理错误&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// errgroup 的优雅写法&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;errgroup&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;WithContext&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Background&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Go&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;callA&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// ... 重复 3 次&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Wait&lt;/span&gt;&lt;span&gt;(); &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// 处理错误&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;显示更多&lt;/span&gt;&lt;span&gt;显示更少&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;看到区别了吗？errgroup 让你的代码从”写满注释的意大利面条”变成了”优雅的法式大餐”。&lt;/p&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;3. errgroup vs WaitGroup：从”包工头”到”精英主管”&lt;a href=&quot;#3-errgroup-vs-waitgroup从包工头到精英主管&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;如果说 &lt;code&gt;sync.WaitGroup&lt;/code&gt; 是个只会数数的包工头，那 &lt;code&gt;errgroup&lt;/code&gt; 就是个精英主管：&lt;/p&gt;&lt;section&gt;&lt;h3&gt;核心优势&lt;a href=&quot;#核心优势&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;共同进退&lt;/strong&gt;：只要一人报错，大家一起收工，避免资源浪费&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;错误收集&lt;/strong&gt;：自动帮你保存第一个返回的非空错误，不用自己写一堆 channel 逻辑&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;资源受控&lt;/strong&gt;：自带 &lt;code&gt;SetLimit&lt;/code&gt; 限流，防止把下游打挂，就像给服务器装了个”防超载保护器”&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;重构清单&lt;a href=&quot;#重构清单&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;从 &lt;code&gt;WaitGroup&lt;/code&gt; 迁移到 &lt;code&gt;errgroup&lt;/code&gt; 的关键步骤：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 1. 初始化（替代 sync.WaitGroup{}）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;errgroup&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;WithContext&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 2. 启动任务（替代 wg.Add(1) + go func()）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Go&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// 你的业务逻辑&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 3. 等待完成（替代 wg.Wait()）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Wait&lt;/span&gt;&lt;span&gt;(); &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// 处理错误&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;迁移检查清单：&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt; 替换 &lt;code&gt;sync.WaitGroup&lt;/code&gt; 为 &lt;code&gt;errgroup.WithContext&lt;/code&gt;&lt;/li&gt;
&lt;li&gt; 将 &lt;code&gt;wg.Add(1)&lt;/code&gt; 和 &lt;code&gt;wg.Done()&lt;/code&gt; 替换为 &lt;code&gt;g.Go()&lt;/code&gt;&lt;/li&gt;
&lt;li&gt; 将错误 channel 替换为 &lt;code&gt;g.Wait()&lt;/code&gt; 返回值&lt;/li&gt;
&lt;li&gt; 确保所有子 goroutine 使用同一个 context&lt;/li&gt;
&lt;li&gt; 添加 &lt;code&gt;ctx.Done()&lt;/code&gt; 检查以支持优雅退出&lt;/li&gt;
&lt;/ul&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;4. 硬核进阶：g.SetLimit 与 g.TryGo&lt;a href=&quot;#4-硬核进阶gsetlimit-与-gtrygo&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;4.1 g.SetLimit(n)：控制并发上限&lt;a href=&quot;#41-gsetlimitn控制并发上限&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;别把服务器当驴使！合理的 &lt;code&gt;SetLimit&lt;/code&gt; 应该参考公式：&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;N = CPU核心数 × (1 + 等待时间 / 计算时间)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;这个公式来自《计算机程序设计艺术》，是并发控制的黄金法则。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;使用示例：&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;SetLimit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;// 最多同时运行 10 个 goroutine&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;实战场景：&lt;/strong&gt; 假设你要处理 1000 个用户的批量操作，每个操作需要调用外部 API。如果不设置 &lt;code&gt;SetLimit&lt;/code&gt;，你的程序会瞬间创建 1000 个 goroutine，可能导致：&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;内存爆炸&lt;/li&gt;
&lt;li&gt;网络连接耗尽&lt;/li&gt;
&lt;li&gt;下游服务被打挂（对方可能会拉黑你）&lt;/li&gt;
&lt;/ul&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 错误示范：无限制并发&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;user&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;range&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;users&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Go&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;callExternalAPI&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;user&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 正确示范：设置合理限流&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;SetLimit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;50&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;// 根据下游服务承受能力调整&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;user&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;range&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;users&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Go&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;callExternalAPI&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;user&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;4.2 g.TryGo：职场试探学&lt;a href=&quot;#42-gtrygo职场试探学&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;code&gt;TryGo&lt;/code&gt; 就像是问女神：“明天有空吗？” 如果女神（Limit 满了）说没空，你立马执行 fallback（降级方案），绝不舔着脸在那等。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;使用示例：&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;SetLimit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;10&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 尝试开启协程，如果并发已满则立即返回 false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;TryGo&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;callHeavyRPC&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;// 没位子了，走备选方案（如走缓存或返回默认值）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;fallback&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;p&gt;&lt;strong&gt;TryGo 的优势：&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;非阻塞操作&lt;/strong&gt;：不会等待，立即返回结果&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;可以立即执行降级策略&lt;/strong&gt;：避免用户等待超时&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;防止资源耗尽导致的雪崩&lt;/strong&gt;：在系统高负载时自动降级&lt;/li&gt;
&lt;/ul&gt;&lt;p&gt;&lt;strong&gt;实战场景：&lt;/strong&gt; 在秒杀系统中，当并发请求超过系统承载能力时，使用 &lt;code&gt;TryGo&lt;/code&gt; 可以立即返回”系统繁忙”，而不是让用户一直等待，最终超时。&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;handleSeckillRequest&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Context&lt;/span&gt;&lt;span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;userID&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;SetLimit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;1000&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;// 系统最大并发处理能力&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!&lt;/span&gt;&lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;TryGo&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;processSeckill&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;userID&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;errors&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;New&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;系统繁忙，请稍后重试&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;5. 完整 Demo：竞争执行 (Race Execution)&lt;a href=&quot;#5-完整-demo竞争执行-race-execution&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;这段代码演示了利用 &lt;code&gt;errgroup&lt;/code&gt; 实现”任一成功/失败即取消其他任务”的硬核操作。&lt;/p&gt;&lt;section&gt;&lt;h3&gt;5.1 代码实现&lt;a href=&quot;#51-代码实现&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;package&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;import&lt;/span&gt;&lt;span&gt; (&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;context&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;errors&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;fmt&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;time&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;&quot;golang.org/x/sync/errgroup&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;SearchData&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Context&lt;/span&gt;&lt;span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;delay&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;time&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Duration&lt;/span&gt;&lt;span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;willFail&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;bool&lt;/span&gt;&lt;span&gt;) (&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;fmt&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Printf&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;🚀 任务 [&lt;/span&gt;&lt;span&gt;%s&lt;/span&gt;&lt;span&gt;] 开始执行...&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;case&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;-&lt;/span&gt;&lt;/span&gt;&lt;span&gt;time&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;After&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;delay&lt;/span&gt;&lt;span&gt;):&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;willFail&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;errors&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;New&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot; 发生故障&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;+&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot; 获取成功&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;case&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;-&lt;/span&gt;&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Done&lt;/span&gt;&lt;span&gt;():&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;fmt&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Printf&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;⏹️ 任务 [&lt;/span&gt;&lt;span&gt;%s&lt;/span&gt;&lt;span&gt;] 收到取消信号，优雅退出。&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;name&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&quot;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Err&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;main&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;errgroup&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;WithContext&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Background&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;resultChan&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;make&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;chan&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;// 缓冲为 1，防止发送者阻塞&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;29&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;tasks&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; []&lt;/span&gt;&lt;/span&gt;&lt;span&gt;struct&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;30&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;31&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;d&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;time&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Duration&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;32&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;bool&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;33&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;34&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&quot;Service-A&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;3&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;time&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Second&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;35&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&quot;Service-B&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;time&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Second&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;true&lt;/span&gt;&lt;span&gt;}, &lt;/span&gt;&lt;span&gt;// 它最快且报错，会触发全局 cancel&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;36&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&quot;Service-C&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;time&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Second&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;false&lt;/span&gt;&lt;span&gt;},&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;37&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;38&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;39&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;range&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;tasks&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;40&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Go&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;41&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;res&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;SearchData&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;n&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;d&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;t&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;f&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;42&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;==&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;43&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;44&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;case&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;resultChan&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;res&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;45&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;                &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;46&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;                &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;47&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;48&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;49&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;50&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;51&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;52&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;go&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;() {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;53&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Wait&lt;/span&gt;&lt;span&gt;(); &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;54&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;fmt&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Printf&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;📢 Wait() 最终捕获错误: &lt;/span&gt;&lt;span&gt;%v&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;55&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;56&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;close&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;resultChan&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;57&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;58&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;59&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;finalRes&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ok&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;-&lt;/span&gt;&lt;/span&gt;&lt;span&gt;resultChan&lt;/span&gt;&lt;span&gt;; &lt;/span&gt;&lt;span&gt;ok&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;60&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;fmt&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Printf&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;🏆 拿到结果: &lt;/span&gt;&lt;span&gt;%s&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;finalRes&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;61&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;} &lt;/span&gt;&lt;span&gt;else&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;62&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;fmt&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Println&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;&quot;&lt;/span&gt;&lt;span&gt;\n&lt;/span&gt;&lt;span&gt;💀 任务全部失败或被取消。&quot;&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;63&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;64&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;显示更多&lt;/span&gt;&lt;span&gt;显示更少&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;5.2 代码解析&lt;a href=&quot;#52-代码解析&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;p&gt;&lt;strong&gt;关键点说明：&lt;/strong&gt;&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Channel 缓冲&lt;/strong&gt;：&lt;code&gt;resultChan&lt;/code&gt; 缓冲为 1，防止发送者阻塞。如果缓冲为 0，当没有接收者时，发送者会永远阻塞。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;优雅退出&lt;/strong&gt;：通过 &lt;code&gt;ctx.Done()&lt;/code&gt; 监听取消信号，确保 goroutine 能够及时退出，避免资源泄漏。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;错误传播&lt;/strong&gt;：&lt;code&gt;g.Wait()&lt;/code&gt; 返回第一个非空 error，这是 errgroup 的核心特性。&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;strong&gt;执行流程：&lt;/strong&gt;&lt;/p&gt;&lt;ol&gt;
&lt;li&gt;Service-B 最快执行（1秒）且报错&lt;/li&gt;
&lt;li&gt;触发全局 &lt;code&gt;cancel()&lt;/code&gt;，取消其他任务&lt;/li&gt;
&lt;li&gt;Service-A 和 Service-C 收到取消信号后优雅退出&lt;/li&gt;
&lt;li&gt;&lt;code&gt;g.Wait()&lt;/code&gt; 返回 Service-B 的错误&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;strong&gt;输出示例：&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;🚀 任务 [Service-A] 开始执行...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;🚀 任务 [Service-B] 开始执行...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;🚀 任务 [Service-C] 开始执行...&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;⏹️ 任务 [Service-A] 收到取消信号，优雅退出。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;⏹️ 任务 [Service-C] 收到取消信号，优雅退出。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;📢 Wait() 最终捕获错误: Service-B 发生故障&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;💀 任务全部失败或被取消。&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;6. 最佳实践总结&lt;a href=&quot;#6-最佳实践总结&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;6.1 使用建议&lt;a href=&quot;#61-使用建议&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;





























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;场景&lt;/th&gt;&lt;th&gt;推荐方案&lt;/th&gt;&lt;th&gt;说明&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;简单并发等待&lt;/td&gt;&lt;td&gt;&lt;code&gt;sync.WaitGroup&lt;/code&gt;&lt;/td&gt;&lt;td&gt;不需要错误处理时，比如批量日志处理&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;需要错误传播&lt;/td&gt;&lt;td&gt;&lt;code&gt;errgroup&lt;/code&gt;&lt;/td&gt;&lt;td&gt;自动收集第一个错误，适合 API 聚合场景&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;需要并发限流&lt;/td&gt;&lt;td&gt;&lt;code&gt;errgroup.SetLimit&lt;/code&gt;&lt;/td&gt;&lt;td&gt;防止资源耗尽，适合批量处理外部请求&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;需要降级策略&lt;/td&gt;&lt;td&gt;&lt;code&gt;errgroup.TryGo&lt;/code&gt;&lt;/td&gt;&lt;td&gt;非阻塞，可立即降级，适合高并发场景&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;6.2 常见陷阱&lt;a href=&quot;#62-常见陷阱&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;section&gt;&lt;h4&gt;陷阱 1：Context 传递不一致&lt;a href=&quot;#陷阱-1context-传递不一致&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 错误示范&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;errgroup&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;WithContext&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Background&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Go&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;process&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Background&lt;/span&gt;&lt;span&gt;()) &lt;/span&gt;&lt;span&gt;// 使用新的 context，无法感知取消&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 正确示范&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;errgroup&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;WithContext&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Background&lt;/span&gt;&lt;span&gt;())&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Go&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;process&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;// 使用同一个 context&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;陷阱 2：Channel 阻塞&lt;a href=&quot;#陷阱-2channel-阻塞&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 错误示范&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;resultChan&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;make&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;chan&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;// 无缓冲&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Go&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;resultChan&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;result&quot;&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;// 如果没有接收者，会永远阻塞&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 正确示范&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;resultChan&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;make&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;chan&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;// 带缓冲&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Go&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;resultChan&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;-&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&quot;result&quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h4&gt;陷阱 3：资源泄漏&lt;a href=&quot;#陷阱-3资源泄漏&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h4&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 错误示范：没有检查 ctx.Done()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Go&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;// 无限循环，即使 context 被取消也不会退出&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;doSomething&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 正确示范：检查 ctx.Done()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Go&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;select&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;case&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;lt;-&lt;/span&gt;&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Done&lt;/span&gt;&lt;span&gt;():&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Err&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;default&lt;/span&gt;&lt;span&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;doSomething&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;显示更多&lt;/span&gt;&lt;span&gt;显示更少&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;6.3 性能优化建议&lt;a href=&quot;#63-性能优化建议&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;合理设置 SetLimit&lt;/strong&gt;：根据系统资源和下游服务承受能力设置，避免过度并发&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;使用 TryGo 实现非阻塞降级&lt;/strong&gt;：在高并发场景下，及时降级比一直等待更重要&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;监控 goroutine 数量&lt;/strong&gt;：使用 &lt;code&gt;runtime.NumGoroutine()&lt;/code&gt; 监控，防止泄漏&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;合理使用 context 超时控制&lt;/strong&gt;：设置合理的超时时间，避免 goroutine 长时间阻塞&lt;/li&gt;
&lt;/ol&gt;&lt;p&gt;&lt;strong&gt;性能对比：&lt;/strong&gt;&lt;/p&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 场景：处理 1000 个外部 API 请求&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 方案 A：无限制并发&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 耗时：~1 秒（最快）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 问题：可能导致下游服务崩溃，内存占用高&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 方案 B：SetLimit(100)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 耗时：~10 秒&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 优势：稳定，不会打挂下游服务&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 方案 C：SetLimit(100) + TryGo + 降级&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 耗时：~10 秒&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;// 优势：稳定 + 用户体验好（立即返回降级结果）&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;7. 实战应用场景&lt;a href=&quot;#7-实战应用场景&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;section&gt;&lt;h3&gt;场景 1：微服务聚合&lt;a href=&quot;#场景-1微服务聚合&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;GetUserInfo&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Context&lt;/span&gt;&lt;span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;userID&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;&lt;span&gt;) (&lt;/span&gt;&lt;span&gt;*&lt;/span&gt;&lt;/span&gt;&lt;span&gt;UserInfo&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt;) {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;errgroup&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;WithContext&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;info&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;UserInfo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Go&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;info&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Profile&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;getProfile&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;userID&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Go&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;info&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Orders&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;getOrders&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;userID&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;16&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;17&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Go&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;18&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;var&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;19&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;info&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Coupons&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;getCoupons&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;userID&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;20&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;21&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;22&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;23&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;if&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Wait&lt;/span&gt;&lt;span&gt;(); &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;!=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;24&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;err&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;25&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;26&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;27&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;&amp;amp;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;info&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;nil&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;28&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;显示更多&lt;/span&gt;&lt;span&gt;显示更少&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;场景 2：批量数据处理&lt;a href=&quot;#场景-2批量数据处理&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;ProcessBatch&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Context&lt;/span&gt;&lt;span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;items&lt;/span&gt;&lt;span&gt; []&lt;/span&gt;&lt;/span&gt;&lt;span&gt;Item&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;errgroup&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;WithContext&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;SetLimit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;50&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;// 控制并发数&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;item&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;range&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;items&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Go&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;processItem&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;item&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Wait&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;&lt;/section&gt;&lt;section&gt;&lt;h3&gt;场景 3：健康检查&lt;a href=&quot;#场景-3健康检查&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h3&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;figure&gt;&lt;figcaption&gt;&lt;/figcaption&gt;&lt;pre&gt;&lt;code&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;1&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;HealthCheck&lt;/span&gt;&lt;span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;context&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Context&lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;2&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;errgroup&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;WithContext&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;3&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;SetLimit&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;5&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;4&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;5&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;services&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; []&lt;/span&gt;&lt;/span&gt;&lt;span&gt;string&lt;/span&gt;&lt;span&gt;{&lt;/span&gt;&lt;span&gt;&quot;db&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;redis&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;mq&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;cache&quot;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&quot;api&quot;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;6&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;7&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;for&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;_&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;svc&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;range&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;services&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;8&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;svc&lt;/span&gt;&lt;span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;:=&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;svc&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;9&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;        &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Go&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;func&lt;/span&gt;&lt;span&gt;() &lt;/span&gt;&lt;span&gt;error&lt;/span&gt;&lt;span&gt; {&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;10&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;            &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;checkService&lt;/span&gt;&lt;span&gt;(&lt;/span&gt;&lt;span&gt;ctx&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;svc&lt;/span&gt;&lt;span&gt;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;11&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span&gt;})&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;12&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;&lt;span&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;13&lt;/div&gt;&lt;/div&gt;&lt;div&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;14&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;    &lt;/span&gt;&lt;span&gt;return&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;g&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;Wait&lt;/span&gt;&lt;span&gt;()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;15&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span&gt;}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div&gt;&lt;div&gt;&lt;/div&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/figure&gt;&lt;div&gt;&lt;/div&gt;&lt;/div&gt;&lt;span&gt;显示更多&lt;/span&gt;&lt;span&gt;显示更少&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;hr /&gt;&lt;/section&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;8. 参考资源&lt;a href=&quot;#8-参考资源&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://pkg.go.dev/golang.org/x/sync/errgroup&quot;&gt;errgroup 官方文档&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://go.dev/doc/effective_go#concurrency&quot;&gt;Go 并发编程最佳实践&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://go.dev/blog/context&quot;&gt;Context 包详解&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/wiki/LockOSThread&quot;&gt;Go 并发模式&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;hr /&gt;&lt;/section&gt;&lt;section&gt;&lt;h2&gt;总结&lt;a href=&quot;#总结&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/a&gt;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;errgroup&lt;/code&gt; 是 Go 并发编程的利器，它不仅解决了 &lt;code&gt;WaitGroup&lt;/code&gt; 的痛点，还提供了更强大的错误处理和资源控制能力。从 WaitGroup 到 errgroup，不仅是工具的升级，更是思维方式的转变——从”只会数数的包工头”到”懂得管理的精英主管”。&lt;/p&gt;&lt;p&gt;掌握 &lt;code&gt;errgroup&lt;/code&gt;，让你的并发代码更优雅、更健壮、更高效。记住，好的并发代码不仅要快，还要稳。就像人生一样，不仅要追求速度，更要懂得何时停下。&lt;/p&gt;&lt;p&gt;&lt;strong&gt;最后送给大家一句话：&lt;/strong&gt; “并发编程就像谈恋爱，既要懂得放手（context cancel），又要懂得坚持（error handling），最重要的是要懂得控制节奏（SetLimit）。”&lt;/p&gt;&lt;hr /&gt;&lt;p&gt;&lt;strong&gt;相关阅读：&lt;/strong&gt;&lt;/p&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Golang Context 详解：从入门到精通&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;Go 性能优化实战指南&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;#&quot;&gt;微服务架构中的并发模式&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/section&gt;&lt;/section&gt;</content:encoded></item></channel></rss>