如何判断协程任务执行是否成功
1 背景简介
工作业务时常有并发任务执行并且需要检查执行结果。协程(goroutine)执行完任务后判断其业务是否“正确”,本质上涉及 结果传递、错误传播、并发控制、可观测性 四个方面。

本文按常见 → 进阶 → 工程化系统说明可用的技术方法,并给出示例。
2 最常用方法channel
- 通过 channel 返回结果 + 错误(推荐)
核心思想:
协程goroutine 不“自己判断成功与否”,而是 返回结果和 error,由调用方判断
type Result struct {
Value int
Err error
}
func worker(ch chan<- Result) {
// 业务逻辑
if false { // 业务失败
ch <- Result{Err: errors.New("业务错误")}
return
}
ch <- Result{Value: 100}
}
func main() {
ch := make(chan Result)
go worker(ch)
res := <-ch
if res.Err != nil {
fmt.Println("失败:", res.Err)
return
}
fmt.Println("成功:", res.Value)
}
适合:
单个 / 少量 goroutine
有明确返回值的业务
- 2 使用 sync.WaitGroup + 共享错误收集
核心思想:
等待所有 goroutine 完成
通过 channel 或 atomic / mutex 收集错误
var wg sync.WaitGroup
errCh := make(chan error, 10)
for i := 0; i < 5; i++ {
wg.Add(1)
go func(i int) {
defer wg.Done()
if i == 3 {
errCh <- fmt.Errorf("任务 %d 失败", i)
}
}(i)
}
wg.Wait()
close(errCh)
for err := range errCh {
if err != nil {
fmt.Println("发现错误:", err)
}
}
适合:
批量并发任务
需要收集多个任务执行状态
2 上下文进阶:工程中最常用的判断方式
- 通过 context.Context 控制 & 判断执行结果
核心思想:
goroutine 接收 context
出错 / 超时 / 取消都会反映到 ctx.Err()
func worker(ctx context.Context) error {
select {
case <-time.After(1 * time.Second):
return nil
case <-ctx.Done():
return ctx.Err()
}
}
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
defer cancel()
err := worker(ctx)
if err != nil {
fmt.Println("失败:", err)
}
}
** 适合:
超时控制
请求级任务
微服务 / RPC / HTTP
- 使用 errgroup(强烈推荐)
errgroup 是 Go 官方扩展库,专门解决:并发执行 + 错误判断
import "golang.org/x/sync/errgroup"
func main() {
var g errgroup.Group
for i := 0; i < 5; i++ {
i := i
g.Go(func() error {
if i == 2 {
return fmt.Errorf("任务 %d 出错", i)
}
return nil
})
}
if err := g.Wait(); err != nil {
fmt.Println("至少一个任务失败:", err)
}
}
** 优点:
自动收集第一个错误
代码简洁
工程实践首选
4 如何“判断业务正确性” 不仅仅是 error
- 明确「业务成功」的判定标准
推荐使用 显式状态结构体:
type TaskResult struct {
Success bool
Code int
Msg string
}
func worker() TaskResult {
if xxx {
return TaskResult{Success: false, Code: 400, Msg: "校验失败"}
}
return TaskResult{Success: true}
}
而不是:
不推荐
func worker() bool
-
使用断言 / 校验逻辑(业务层)
func validate(result Result) error { if result.Value <= 0 { return errors.New("结果不合法") } return nil }
在 goroutine 外统一校验。
5 工程化手段(生产环境必备)
-
日志 + Trace ID(定位正确性)
log.WithFields(log.Fields{ "task_id": id, "result": result, }).Info("task finished")
判断是否正确 ≠ 只靠返回值
还需要 日志 + 上下文
- 指标 & 监控(最终判断)
成功率
失败次数
超时数量
task_success_total
task_failure_total
Prometheus / OpenTelemetry
** 常见错误做法(避免)
goroutine 里 panic 当失败
goroutine 里打印日志就当处理完成
不返回结果,只靠全局变量
不等待 goroutine 就判断成功
6 小结
选型建议
单任务推荐方式 channel + error
多任务推荐方式 WaitGroup + error channel
复杂并发推荐方式 errgroup
超时取消推荐方式 context
工程化推荐方式 errgroup + context + 日志 + 监控。
- 点赞
- 收藏
- 关注作者
评论(0)