Go语言用panic/recover+defer实现异常处理,recover仅在defer函数中有效且限于当前goroutine;需在易错逻辑外层封装safeRun等模式,子goroutine须独立加recover;recover后不继续执行panic点,仅恢复调度并返回。

Go语言中没有传统意义上的try-catch机制,而是通过panic和recover配合defer来实现运行时异常的捕获与恢复。关键在于:recover只能在defer函数中调用才有效,且仅能捕获当前goroutine中的panic。
recover必须配合defer使用
recover不是全局拦截器,它只在defer延迟执行的函数中调用时才起作用。如果写在普通逻辑里,返回值始终为nil,无法捕获任何panic。
- 正确写法:在可能panic的函数内,先用
defer注册一个匿名或命名函数,在其中调用recover() - 错误写法:把
recover()放在if判断里、或者放在panic之后但不在defer中
典型安全封装模式
常见做法是将易出错逻辑包裹进一个带recover的闭包,统一处理异常:
func safeRun(f func()) {
defer func() {
if r := recover(); r != nil {
log.Printf("panic recovered: %v", r)
// 可记录日志、上报监控、返回默认值等
}
}()
f()
}
调用方式:safeRun(func() { riskyOperation() })。这样即使riskyOperation触发panic,程序也不会退出,而是继续执行后续逻辑。
立即学习“go语言免费学习笔记(深入)”;
注意goroutine隔离性
每个goroutine有独立的panic/recover作用域。主goroutine中defer的recover无法捕获子goroutine里的panic。
- 子goroutine需自行加defer+recover,例如启动时就包装:
go func() { defer safeRecover(); doWork() }() - HTTP服务中,标准
http.ServeMux已内置recover(如net/http包),但自定义handler仍建议手动加一层防护
recover后不能“继续执行”panic发生点
recover的作用是让程序从panic状态恢复正常调度,但它不会回到panic发生的那行代码继续执行。控制权会回到defer所在函数的末尾,然后按正常流程返回。
- 例如:函数A中defer了recover,A内部某处panic → 执行defer函数 → recover成功 → A函数直接返回,不执行panic之后的代码
- 因此,recover适合做“兜底清理”和“错误转化”,不适合用来“重试”或“修正错误后续跑完”










