外观
defer、错误处理与 panic
- 状态:未准备
- 适用方向:Go 全栈 / Go 后端
- 最近复习:待填写
- 下次复习:待安排
一句话回答
defer 退出时按后进先出执行,参数注册时求值;预期失败用 error 返回,panic 用于异常,recover 只在同一 goroutine 的有效延迟调用中起作用。
原理解释
go
func answer() (n int) {
defer func() { n++ }()
return 1 // 先赋给 n,defer 再执行,结果为 2。
}defer fmt.Println(x) 提前确定 x;闭包中访问 x 则执行时读取变量。循环里 defer 要到整个函数退出才释放资源,可提取小函数及时关闭。
fmt.Errorf("load user: %w", err) 保留错误链;用 errors.Is 识别目标错误、errors.As 提取错误类型,不靠字符串判断。HTTP 层映射稳定状态码与对外信息,日志保留排障上下文。
recover 在 defer 函数中直接调用;父 goroutine 不能恢复子 goroutine 的 panic。恢复后退出正在展开的函数,不回到 panic 行继续。os.Exit 不执行 defer。
场景与边界
请求边界 recovery 能隔离部分异常,但不能吞错后返回成功;响应已经写出时也不能可靠改成统一 JSON 错误。业务校验失败通常用 error。
项目中的应用
沿 EinoTalk 落库流程检查错误是否只记录日志;日志不等于可靠重试或调用方已获知失败。
常见追问
- defer 能修改未命名返回值吗? 返回表达式已求值,修改局部变量通常不改变返回副本。
- Close 错误要处理吗? 关键写入和提交收尾需要评估,与主错误要有优先级。
- 所有 panic 都能恢复吗? fatal error、进程退出等不在普通 recover 保证内。