Go语言异常处理:panic与recover的正确用法

Ada
Ada
发布时间:2026-10-13 | 2人浏览过
原创

Go语言不支持传统的 try-catch-finally 异常处理,而是推荐多值返回处理错误。对于程序不可恢复的异常情况,使用 panic 抛出并配合 recover 捕获。本文详解 panic 和 recover 的原理、跨协程陷阱及性能表现。

基本概念与使用示例

在Go语言中,当遇到真正的异常(如除数为0、数组越界)时,可以使用 panic 中断普通执行流程,并在 defer 延迟函数中通过 recover 捕获该异常,从而恢复正常执行或进行优雅退出。

注意: recover 必须定义在 defer 匿名函数内,且 defer 必须在调用可能触发 panic 的代码之前声明,否则无法捕获。

package main
import "fmt"
func main() {
	fmt.Println("c")
	// defer 必须在 panic 之前声明
	defer func() {
		fmt.Println("d")
		if err := recover(); err != nil {
			fmt.Println(err) // 捕获 panic 传入的内容
		}
		fmt.Println("e")
	}()
	f() // 调用 f
	fmt.Println("f") // panic 发生前会打印,发生后不会执行
}
func f() {
	fmt.Println("a")
	panic("异常信息")
	fmt.Println("b") // 不会执行
}

上述代码输出结果:

  • c
  • a
  • d
  • 异常信息
  • e

不同作用域下的 Recover 表现

1. 子函数 Panic,主函数 Recover

如果在子函数中发生 panic,而主函数中有对应的 defer recover,可以成功捕获。此时只有发生 panic 的那个函数后续代码不再执行,后续的主流程函数仍可运行。

func TestPanic(t *testing.T) {
	defer func() {
		if err := recover(); err != nil {
			println("recovered")
		}
	}()
	subFun()
	subFun() // 第二次调用 subFun 依然正常执行
}
func subFun() {
	println("subFun")
	panic("subFun panic")
}

输出:subFun、recovered、subFun。

2. 子协程 Panic,主协程 Recover(关键陷阱)

panic 和 recover 必须位于同一个协程内才有效。如果 go 关键字启动的新协程发生 panic 而没有在该协程内部 recover,将导致整个程序崩溃,主协程的 recover 无法拦截。

func subFun(i int) {
	fmt.Println("subFun,i=", i)
	panic("subFun panic")
}
func TestSubGoPanic(t *testing.T) {
	defer func() {
		if err := recover(); err != nil {
			println("recovered2")
		}
	}()
	go subFun(3) // 新协程 panic 无法被这里捕获
	subFun(4)    // 当前协程 panic 被捕获
	println("finish")
}

结果分析:subFun(4) 触发的 panic 被主协程的 recover 捕获,打印出 recovered2;但 subFun(3) 所在协程的 panic 未被拦截,最终导致进程崩溃退出。

性能对比与安全建议

性能考量: Go 官方推崇使用返回值而非 panic。然而在实际的高并发压测中,由于 return error 往往涉及堆内存分配(特别是 error 实现为接口的动态派发),有时 recover 的性能甚至优于传统的错误返回。但这属于特定场景优化,不建议作为常规业务逻辑处理手段。

安全使用原则

为防止偶发 panic 导致服务重启,可采用封装策略:对于核心 Goroutine,在其入口处统一添加 recover 逻辑;或者对底层可能报错的第三方库,在使用 go func() 调用时,在该 goroutine 内部包裹 recover 块。

总结

Go 语言中,错误应优先使用多返回值处理,panic 仅用于致命错误或框架级兜底。牢记“同协程捕获”的铁律,并在必要时做好防护。

以上就是Golang异常处理之优雅地控制和处理异常的详细内容,更多关于Golang异常处理内容请搜索本站以前的文章或继续浏览下面的相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表