使用sync.WaitGroup和channel可处理Go中简单任务依赖,复杂场景宜构建DAG调度器或采用第三方库,结合context实现超时控制与错误传播。

在Go语言中处理并发任务依赖,核心是协调多个任务的执行顺序,确保有依赖关系的任务在前置任务完成后才开始。常见的场景包括:数据加载、服务启动、工作流引擎等。Golang本身没有内置的依赖调度器,但可以通过语言特性灵活实现。
使用sync.WaitGroup控制任务完成
当多个并行任务之间没有依赖,但需要等待它们全部完成时,sync.WaitGroup 是最直接的选择。如果任务间存在层级依赖(如A和B完成后才能执行C),可以组合使用WaitGroup与goroutine嵌套。
- 为每个前置任务调用Add(1),完成后调用Done()
- 依赖任务通过Wait()阻塞,直到所有前置任务结束
示例:任务C依赖A和B
var wg sync.WaitGroupgo func() { defer wg.Done() // 执行任务A }()
go func() { defer wg.Done() // 执行任务B }()
go func() { wg.Wait() // 等待A和B完成 // 执行任务C }()
使用channel传递就绪信号
channel是Go中更灵活的同步机制。可通过无缓冲或带缓冲channel发送“完成”或“就绪”信号,实现任务间的解耦依赖。
立即学习“go语言免费学习笔记(深入)”;
- 前置任务完成时向channel写入信号
- 依赖任务从channel读取信号后启动
- 多个依赖可使用select监听多个channel
例如:任务C等待A或B任一完成
doneA := make(chan bool) doneB := make(chan bool)// 任务A go func() { // 执行逻辑 doneA <- true }()
// 任务C go func() { select { case <-doneA: // A完成,执行C case <-doneB: // B完成,执行C } }()
构建有向无环图(DAG)调度器
对于复杂依赖关系,可将任务建模为DAG节点,使用拓扑排序决定执行顺序,并结合并发执行无依赖任务。
- 每个任务记录入度(依赖数)和后续任务列表
- 初始将入度为0的任务加入队列并发执行
- 每完成一个任务,将其后继入度减1;若减至0则提交执行
这种模式适合工作流系统,能最大化并行度,同时保证依赖顺序。
利用第三方库简化开发
已有成熟库如go-actor、temporal 或轻量级的 dag-scheduler 可直接支持任务依赖调度。这些库通常提供DSL定义流程、错误重试、超时控制等高级功能。
对于简单项目,推荐手动实现;复杂业务建议选用稳定库降低维护成本。
基本上就这些。关键是根据依赖复杂度选择合适方案:简单场景用WaitGroup或channel,复杂流程上DAG模型。不复杂但容易忽略的是错误传播和超时控制,记得为关键任务设置context.WithTimeout。










