章节

12.3 recover 恢复程序

本篇学习 recover 捕获 panic 的写法,并能在 defer 中拦截 panic、让外层流程继续执行。

recover 恢复程序

概念说明

recover 用于捕获当前 goroutine 中正在发生的 panic。
它必须在 defer 调用的函数中使用,才能拦截 panic 并让程序恢复到可控状态。

恢复 panic 不等于问题消失。
捕获后通常还要记录日志、返回错误或做兜底处理。

语法/规则

  1. recover() 只有在 deferred 函数中直接调用才有效。
  2. 没有发生 panic 时,recover() 返回 nil
  3. recover 只能捕获当前 goroutine 的 panic。
  4. 捕获 panic 后,当前函数不会回到 panic 发生点继续执行。
  5. 不要用 recover 隐藏所有错误,否则排查问题会更困难。

recover 示例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package main

import "fmt"

func safeRun() {
	// defer 会在 safeRun 即将结束时执行。
	// 如果函数里发生了 panic,Go 会先执行 defer,再决定是否继续向外抛出 panic。
	defer func() {
		// recover 必须在 defer 的函数里直接调用才有效。
		// 如果当前正在处理 panic,这里就能拿到 panic 的内容。
		if err := recover(); err != nil {
			fmt.Println("recovered:", err)
			// 一旦 recover 成功,这次 panic 就被拦住了。
			// safeRun 不会回到 panic 那一行继续执行,而是直接结束并返回给调用者。
		}
	}()

	fmt.Println("safeRun: start")

	// 这里触发 panic。
	// 从这一行开始,safeRun 后面的普通代码都不会继续执行。
	panic("something wrong")

	// 这一行永远不会执行,因为 panic 发生后流程会立刻转去执行 defer。
	// fmt.Println("safeRun: end")
}

func main() {
	// safeRun 内部已经把 panic recover 掉了,
	// 所以 panic 不会继续传到 main。
	safeRun()

	// 所谓“恢复”,指的是程序没有因为这次 panic 整体崩溃,
	// main 还能继续执行后面的代码。
	fmt.Println("main continues")
}

这里的“恢复”不是回到 panic("something wrong") 那一行后面继续跑,
而是把原本会继续向上传播的 panic 截住,让 safeRun() 正常结束,随后 main() 继续往下执行。

输出结果:

1
2
3
safeRun: start
recovered: something wrong
main continues

常见错误

  1. 在普通函数调用中直接写 recover(),无法捕获 panic。
  2. 以为 recover 可以跨 goroutine 捕获 panic,实际每个 goroutine 要自己处理。
  3. 捕获后什么也不做,导致错误被静默吞掉。
  4. 认为 recover 后会回到 panic 那一行继续执行,实际不会。
本文禁止转载
使用 Hugo 构建
主题 StackJimmy 设计 由 Hobin 魔改
最近构建时间:2026-04-17 19:07:48 CST
载入天数...载入时分秒...
发表了 1 篇文章 · 发表了 152 篇笔记 · 总计 18 万 0 千字