跳到正文

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 保证内。

参考资料 ​

理解机制,讲清取舍,用复盘检验掌握。