不能直接用 sync.waitgroup 替代 errgroup.group,因为 waitgroup 只等待完成、不处理错误,而 errgroup.group 支持错误传播、短路返回首个 error,并集成 context 取消机制。

Go 标准库 sync 包够用,但不覆盖所有高阶并发场景;真正需要 x/sync(即 golang.org/x/sync)时,往往是因为标准库缺了「带超时的等待」「带错误传播的组控」「防重入的单次执行」这类能力。
为什么不能直接用 sync.WaitGroup 替代 errgroup.Group
标准库 sync.WaitGroup 只管“是否完成”,不管“是否出错”。一旦某个 goroutine panic 或返回 error,主流程完全无感知,wg.Wait() 仍会返回,错误被静默吞掉。
-
errgroup.Group在Wait()时返回第一个非 nil error,天然支持错误短路 - 它内部封装了
sync.WaitGroup,但额外维护一个err字段,用sync.Once保证只记录首个错误 - 若需取消全部子 goroutine,可传入
context.Context,而原生WaitGroup无此能力
singleflight.Group 解决什么问题,以及它和 sync.Once 的本质区别
sync.Once 保证「整个程序生命周期内只执行一次」;singleflight.Group 保证「同一时刻对相同 key 的多次调用,只触发一次底层操作,其余调用等待并复用结果」——这是典型的缓存穿透防护模式。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 典型场景:多个 goroutine 同时查同一个用户 ID,后端 DB/HTTP 请求只发一次,其余等待返回
- key 是字符串,不是全局状态;不同 key 互不影响,
Once没有 key 概念 - 它的
Do(key, fn)返回值包含val和err,且fn执行失败时,后续同 key 调用仍会重试(除非显式设置Forget),而Once.Do一旦 panic 就永久失效
semaphore.Weighted 与手动实现计数信号量的坑
手写基于 chan struct{} 或 sync.Mutex + int 的信号量,容易在超时、抢占、公平性上翻车;semaphore.Weighted 是官方推荐的替代方案。
- 支持带
context.Context的Acquire,可中断等待,避免 goroutine 永久阻塞 - 内部使用
sync.Pool复用等待节点,避免高频 Acquire/Release 触发 GC - 注意:它不保证 FIFO 公平性,饥饿可能发生在高并发争抢下;如需严格顺序,得自己加队列层
- 初始化时传入的
weight是最大并发数,但Acquire可传不同权重值(比如大任务占 3 单位,小任务占 1),这是原始 chan 无法表达的
真正难的不是选哪个类型,而是判断「该不该用 x/sync」:如果业务里反复出现 context 超时传递、错误聚合、key 级去重或动态权重调度,说明标准库原语已到边界,这时候引入 x/sync 不是炫技,而是让并发逻辑可读、可测、可退火。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










