recover只能在defer函数中调用才有效,直接调用返回nil;不能跨goroutine捕获panic,recover后函数立即return,后续语句不执行;必须在panic前注册defer,且recover需置于匿名函数中,http handler中需为每个goroutine单独加recover。

recover 只能在 defer 函数里调用才有效,直接写 recover() 永远返回 nil。它不能跨 goroutine 捕获 panic,也不能恢复 panic 后的执行流——函数在 panic 被 recover 后立即 return,后续语句不执行。
recover 必须放在 defer 中,且顺序不能错
这是最常踩的坑:把 recover() 写在普通位置,或放在 panic() 之后但没包在 defer 里。
-
defer必须在panic发生前注册,否则不会执行 - 多个
defer按后进先出(LIFO)执行,recover应该放在最内层的defer中 - 典型错误写法:
defer recover()—— 这是调用recover并把返回值 defer 执行,毫无意义 - 正确写法必须是匿名函数:
defer func() { r := recover(); if r != nil { /* 处理 */ } }()
HTTP handler 里 recover 经常失效,因为 goroutine 隔离
Go 的 HTTP server 对每个请求启动一个新 goroutine,recover() 只对当前 goroutine 生效。
- 如果 panic 发生在子 goroutine(比如
go doSomething()),主 handler 的defer捕不到 - Gin/Echo 自带的
Recovery()中间件只包裹 handler 主 goroutine,不处理内部起的 goroutine - 所有显式
go启动的函数,都得自己加defer+recover,或统一走safeGo()封装 - 别依赖
debug.SetPanicOnFault(true),它只对非法内存访问信号有效,对panic("xxx")完全无效
recover 后无法继续原逻辑,副作用不能自动回滚
recover 不是 try-catch,它只是阻止崩溃、交还控制权,不提供“重试”或“回退”能力。
-
panic前已执行的代码(如file.Write()、ch 、<code>m[key] = val)不会被撤销 - 想实现降级逻辑,得靠显式
if err != nil判断 + 提前返回,而不是靠 recover 吞掉 panic 再续跑 - 若需记录完整上下文,
recover()返回的是interface{},建议配合runtime/debug.Stack()获取栈迹,别只打r
真正兜底的方式不是找“全局捕获”,而是分层设防:handler 层用中间件、goroutine 层用 safeGo、main 入口加 defer、关键第三方调用点改用 error 判断——这些地方稍一遗漏,panic 就会逃逸。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











