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

为何Go中recover无法捕获所在函数内goroutine触发的panic?

为什么你的recover没捕获到goroutine里的panic?

核心原因很简单:Go语言中,recover()只能捕获当前goroutine内触发的panic,不同goroutine之间的panic是完全隔离的,跨goroutine无法实现panic捕获。

具体到你的代码,拆解执行流程就能明白:

  • wrapRecover函数里的defer是注册在执行TestRecover的测试goroutine中的。
  • 你传给wrapRecover的匿名函数,仅仅是调用group.Go启动了一个新的goroutine,这个匿名函数本身很快就执行完毕,随后wrapRecover函数返回,它的defer也会跟着执行(这时候新goroutine还在sleep,根本没触发panic)。
  • 1秒后,新goroutine里的fn()触发panic,但这个panic属于那个独立的goroutine,和之前的测试goroutine没有关联,自然不会被已经执行完的wrapRecover里的recover捕获。

正确的修复方式

要捕获新goroutine里的panic,必须把recover()逻辑放在同一个goroutine的defer中。比如修改group.Go中的匿名函数:

group.Go(func() error {
    defer func() {
        if rec := recover(); rec != nil {
            fmt.Println("recover")
        }
    }()
    fn()
    return nil
})

或者封装一个通用的带panic捕获的函数,复用起来更方便:

func wrapGoroutineWithRecover(f func()) func() error {
    return func() error {
        defer func() {
            if rec := recover(); rec != nil {
                fmt.Println("recover")
            }
        }()
        f()
        return nil
    }
}

// 调用时直接传入即可
group.Go(wrapGoroutineWithRecover(fn))

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 17:32:39