☰
Go 面试突击:defer、recover、panic 经典 20 问
2026/9/30 7:10:33 网站建设 项目流程

Go 面试突击:defer、recover、panic 经典 20 问

panic 和 recover 是 Go 的最后防线。掌握三者的执行机制,是 Gopher 项目的"基本礼仪"。

一、defer 基础

Q1. defer 执行顺序?

LIFO(后入先出)。

Q2. defer 内修改返回值能影响外面吗?

若返回值具名,可以;否则不行。

Q3. defer 调用时机?

return 语句执行前。

Q4. defer 内修改循环变量?

fori:=0;i<3;i++{deferfunc(iint){fmt.Println(i)}(i)}// 输出 2 1 0

参数预计算。

Q5. defer 在 panic 后执行吗?

执行。

Q6. defer 性能?

低频用 OK。1.14+ 大部分 defer 编译器会 inline,免 runtime 开销。

Q7. defer 用于资源释放常见吗?

文件、锁、连接、ctx cancel 等。

Q8. defer 用于 trace 计数器?

defer trace.Counter("foo").Inc()。

Q9. defer 让方法变慢多少?

几纳秒到几十纳秒级。

二、panic 基础

Q10. panic 与 exception 区别?

Go panic 是语言级机制,exception 是语言级异常。Go 用 panic/recover,Java 用 exception。

Q11. panic 后整个进程死吗?

无 recover 则 panic 沿栈冒泡到 main,整个进程死。

Q12. panic 的副作用?

defer 仍执行;栈展开;状态机被打破。

Q13. panic 后函数还能用吗?

调用方 recover 后,goroutine 继续。

Q14. recover 何时调用才有用?

在 defer 函数内直接调用。

Q15. recover 多次调用可以吗?

第一次后无 effect,但可多次写。

Q16. 在 goroutine 里 panic?

只能由那个 goroutine recover。

Q17. panic 子函数影响父吗?

影响,子函数 panic 上抛。

三、实战

Q18. 全局 recover 中间件?

funcRecovery(c*gin.Context){deferfunc(){ifr:=recover();r!=nil{log.Printf("panic: %v\n%s",r,debug.Stack())c.AbortWithStatusJSON(500,gin.H{"msg":"internal"})}}()c.Next()}

Q19. 测试 panic 应该用什么?

assert.Panics(func(){f()})

Q20. 让 panic 输出的栈不重复?

errors stacktrace vs runtime/debug.Stack:errors.New不带栈,需要pkg/errors包装或runtime.Caller。

四、避坑

  1. 不要用 panic 实现业务错误——error 才是正路
  2. 不要在 M 关闭前忘记 recover——崩进程
  3. recover 仅为兜底——测试覆盖到不要靠它
  4. panic 包装成 err 后丢上下文——带 stack

五、总结与展望

defer + panic + recover 三件套是 Go 容错核心。最佳实践:

  • 业务层用 error
  • goroutine 用 defer recover 兜底
  • HTTP/gRPC 入口统一 Recovery 中间件

未来 Go 1.24 可能引入panic为 typed panic 值。

六、参考文献

  • Go 官方 blog:Defer, Panic, and Recover
  • cmd/compile walk.go

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询