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

从panic恢复的值是否始终为Go语言的error类型?

在Go中将Panic转为Error的正确方式

绝对不能安全假设所有panic都是error类型,Go语言允许panic()抛出任意类型的值——字符串、整数、自定义结构体甚至nil都有可能。

示例A的隐患

示例A里用r.(error)做强制类型断言,如果panic抛出的不是error类型(比如panic("invalid input")或panic(500)),这个断言会直接失败,触发二次panic,而此时defer函数里已经没有recover逻辑了,程序会直接崩溃,完全达不到“捕获所有panic转为error”的目的。

示例B的合理性

示例B用fmt.Errorf("%s", r)处理panic值是更安全的选择:

  • Go的格式化输出%s会自动调用值的String()方法(如果该类型实现了这个接口);
  • 如果没有实现String(),会用默认格式输出值的类型和内容;
  • 无论panic抛出什么类型,这个操作都不会触发新的panic,能保证所有场景下都把panic转为error返回。

更健壮的优化写法

如果想兼顾“保留原error信息”和“兼容所有panic类型”,可以先尝试类型断言,失败再格式化:

func API3() (err error) {
    defer func() {
        if r := recover(); r != nil {
            switch v := r.(type) {
            case error:
                err = v // 保留原error的类型和细节
            default:
                err = fmt.Errorf("panic occurred: %v", v) // 其他类型转为格式化的error
            }
        }
    }()
    mayPanic()
    return
}

这种写法既不会丢失原error的上下文(比如自定义error的堆栈信息),又能安全处理非error类型的panic。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 14:20:01