You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

这段Go代码是否线程安全?是否需要使用互斥锁?

Go异步任务结果追踪实现解析

看起来你是在搭建Go语言里异步任务的结果追踪机制,我来帮你拆解这个实现的核心逻辑,以及如何正确使用它:

先把完整的代码实现放出来,方便对照理解:

type Result struct {
    doneCh chan struct{}
    err    error
}

// Done 返回只读通道,当任务完成时该通道会被关闭
func (r *Result) Done() <-chan struct{} {
    return r.doneCh
}

func doWork() *Result {
    r := Result{doneCh: make(chan struct{})}
    go func() {
        var err error
        defer func() {
            r.err = err
            close(r.doneCh)
        }()
        // 这里写实际要执行的任务逻辑,比如:
        // err = someHeavyTask()
    }()
    return &r
}

核心设计思路拆解

  • Result结构体的职责:
    • doneCh:用无缓冲的struct{}通道传递任务完成信号——通道关闭就代表任务结束,这种设计比带值通道更轻量,毕竟我们只需要“完成”这个状态,不需要额外数据。
    • err:存储任务执行时的错误,外部要在任务完成后再读取这个值才有效。
  • doWork的异步逻辑:
    • 先初始化Result实例并创建doneCh,随后启动goroutine执行实际任务。
    • 用defer语句兜底:不管任务是正常跑完还是中途出错,最终都会把错误赋值给r.err,并关闭doneCh——这保证了外部总能收到完成通知,不会出现永久阻塞的情况。
  • Done()方法的作用:
    返回只读通道类型,避免外部代码意外关闭通道或发送数据,符合Go语言的封装安全原则。

正确使用示例

要等待任务完成并检查结果,你可以这么写:

package main

import "fmt"

// 这里插入上面的Result和doWork代码

func someHeavyTask() error {
    // 模拟耗时任务
    // time.Sleep(2 * time.Second)
    return nil // 改成return fmt.Errorf("任务失败")可测试错误场景
}

func main() {
    res := doWork()
    // 等待任务完成
    <-res.Done()
    if res.err != nil {
        fmt.Printf("任务执行失败: %v\n", res.err)
    } else {
        fmt.Println("任务成功完成")
    }
}

额外优化建议

如果任务逻辑可能触发panic,建议在defer里加上recover()捕获,避免程序崩溃:

defer func() {
    if p := recover(); p != nil {
        err = fmt.Errorf("任务panic: %v", p)
    }
    r.err = err
    close(r.doneCh)
}()

内容的提问来源于stack exchange,提问作者George Robinson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:34:18