位置:首页 > Go > Go中安全等待多个Goroutine完成并实时处理结果的方法

Go中安全等待多个Goroutine完成并实时处理结果的方法

时间:2026-08-15  |  作者:星际追番人  |  阅读:0

本文讲解如何使用 sync.WaitGroup 配合 channel 实现:在启动多个 goroutine 并发执行任务的同时,实时消费返回结果,并在所有任务完成后优雅关闭 channel,避免死锁。

Go 中如何安全等待多个 Goroutine 完成并实时处理结果

本文讲解如何使用 sync.WaitGroup 配合 channel 实现:在启动多个 goroutine 并发执行任务的同时,实时消费返回结果,并在所有任务完成后优雅关闭 channel,避免死锁。

在 Go 里,让多个任务并发跑起来,再把结果一个个接住处理,是非常典型的场景。比如调用外部命令 os/exec,很多时候就是这么组织的。不过,这里有个特别容易踩中的坑:如果对一个没有关闭的无缓冲 channel 直接使用 for range,程序往往会卡死,因为它根本不知道“什么时候才算读完了”。出现 fatal error: all goroutines are asleep - deadlock! 这种报错,通常就是这个问题在作祟。说到底,原因并不复杂:range 会一直阻塞着等下一个值,而负责发送的 goroutine 已经退出,却没有显式关闭 channel,结果接收方就只能一直等下去,最终陷入死锁。

解决方案的核心是分离“发送完成信号”与“结果接收逻辑”,借助 sync.WaitGroup 精确跟踪所有 goroutine 的生命周期,并在全部完成时关闭 channel。以下是推荐实现:

package main

import (
"fmt"
"sync"
)

func execTask(input int, results chan<- int) {
// 模拟耗时操作(如 os/exec.Run)
result := input * 2 // 示例计算结果
results <- result
}

func main() {
tasks := []int{1, 2, 3, 4, 5}
var wg sync.WaitGroup
results := make(chan int)

// 启动所有任务 goroutine,并注册 WaitGroup 计数
wg.Add(len(tasks))
for _, task := range tasks {
go func(t int) {
defer wg.Done() // 任务完成时递减计数
execTask(t, results)
}(task)
}

// 单独 goroutine 等待全部任务结束,并关闭 channel
go func() {
wg.Wait()
close(results) // 关键:关闭 channel,使 range 自动退出
}()

// 主 goroutine 实时接收并处理结果(无需等待全部完成)
for result := range results {
fmt.Printf("Received: %dn", result)
//  此处可立即处理每个结果:写入数据库、触发回调、聚合统计等
// 甚至可在此启动新 goroutine 进行后续异步处理
}
fmt.Println("All tasks completed.")
}

关键要点说明:

  • sync.WaitGroup 提供线程安全的计数器,Add() 初始化总数,Done() 在每个 goroutine 结束时调用,Wait() 阻塞直到计数归零;
  • close(results) 必须由唯一确定所有发送者已退出的 goroutine 执行(此处为 go func(){...}()),否则可能引发 panic;
  • for range results 会在 channel 关闭且缓冲区清空后自然退出,无需额外标志位或超时;
  • 实时性保障:结果一旦写入 channel,主循环立即处理,无需等待其他 goroutine 完成——这正是并发模型的优势;
  • 若需限制并发数(避免资源耗尽),可在外层加 semaphore 或使用带缓冲的 worker pool,而非简单 go execTask(...)。

综上,WaitGroup + close(channel) 是 Go 中协调“多生产者、单消费者”场景的标准范式,兼顾安全性、简洁性与实时响应能力。

免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。

相关文章

更多

精选合集

更多

大家都在玩

热门话题

大家都在看

更多