recover 必须在 defer 函数中调用才有效,仅对当前 goroutine 最近一次未处理的 panic 生效,返回 interface{} 需类型断言,且无法跨 goroutine 捕获 panic。

recover 只有在 defer 函数里调用才有效,否则返回 nil —— 这不是限制,而是设计前提,跳过这点直接写 recover 就等于没写。
recover 必须在 defer 中调用,且仅对当前 goroutine 有效
recover 不是全局“兜底”函数,它只作用于当前 goroutine 最近一次未被处理的 panic。如果在普通函数里调用 recover(),它永远返回 nil;如果在 goroutine 外部(比如主函数里)试图捕获另一个 goroutine 的 panic,也完全无效。
- panic 是 goroutine 局部的:每个 goroutine 有自己的 panic 栈,
recover()只能捕获本 goroutine 的 - 必须搭配
defer:只有 defer 函数执行时,panic 还处于“待恢复”状态,此时recover()才能取到 panic 参数 - goroutine 泄漏风险:如果启动了新 goroutine 却没加 defer + recover,一旦 panic 就直接崩溃,不会通知主流程
defer 函数中修改命名返回值,而不是用 return 语句
很多人误以为能在 defer 里写 return nil, errors.New("...") 来覆盖外层函数返回值,这是语法错误。Go 不允许 defer 函数改变外层函数签名,但允许它修改已声明的命名返回参数。
诊断并恢复通过 SSH 隧道连接的 OpenClaw 节点。用于解决配对必需错误、隧道冲突、远程端点错误以及 SSH 目标配置错误等问题。
- 正确写法:
func foo() (result string, err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("panic: %v", r) } }() ... } - 错误写法:
defer func() { if r := recover(); r != nil { return "", errors.New("...") } }()—— 这里的return属于 defer 匿名函数自身,对外层无影响 - 命名返回值本质是变量:
err在函数体里可读可写,defer 内部赋值会真实生效
panic 参数类型不统一,recover 返回 interface{},需做类型断言
panic() 能传任意值:string、error、自定义 struct,甚至 nil。而 recover() 总是返回 interface{},不做断言就无法安全使用。
- 常见 panic 类型:
panic("file not found")→recover()返回string;panic(errors.New("io timeout"))→ 返回error - 推荐统一处理方式:先判断是否为
error,再 fallback 到fmt.Sprint(r),避免 panic 字符串含敏感信息直接暴露 - 注意空 panic:
panic(nil)合法,recover()返回nil,但此时r == nil不能等同于“没 panic”,要结合上下文判断
并发场景下每个 goroutine 必须独立加 defer + recover
Go 不支持跨 goroutine 捕获 panic。你不能靠主 goroutine 的 recover 去 catch 子 goroutine 的崩溃 —— 它们彼此隔离,子 goroutine panic 后只会自己终止,还可能留下资源泄漏。
- 典型错误模式:
go riskyFunc()后不加任何保护,一旦riskyFuncpanic,整个程序可能卡死或泄露文件句柄 - 正确做法:所有可能 panic 的 goroutine 内部必须包裹
defer func() { recover() }() - 更稳妥方案:封装一个带 recover 的 goroutine 启动器,比如
go safeRun(func() { ... }),避免重复写样板代码
真正容易被忽略的不是 recover 怎么写,而是 panic 发生时的调用栈已经丢失 —— recover 拿不到原始 panic 位置,除非你在 panic 前手动记录 debug.PrintStack() 或用第三方库增强上下文。这导致线上定位问题时,光靠 recover 日志往往不够。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










