在 Go 语言中,panic 和 recover 是用于处理运行时异常的关键字。以下是它们的用法总结和示例:
1. panic 的作用
- 触发条件:当程序遇到无法恢复的严重错误时(如不可预料的逻辑错误、依赖项缺失等),panic 会终止当前函数的执行,并逐层向上触发 defer,最后若未被 recover 捕获,程序会崩溃。
- 适用场景:
- 初始化阶段的关键资源缺失(如配置文件、数据库连接)。
- 代码逻辑中出现不可恢复的异常(如断言失败)。
2. 基本用法
1
2
3
4
5
6
7
8
9
10
11
12
|
package main
import \"fmt\"
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println(\"Recovered from panic:\", r)
}
}()
fmt.Println(\"Start\")
panic(\"something bad happened\") // 触发 panic
fmt.Println(\"End\") // 不会执行
}
|
输出:
Start
Recovered from panic: something bad happened
3. recover 的使用规则
- 必须与 defer 结合:recover 只能在 defer 函数中生效。
- 仅在当前 goroutine 有效:无法捕获其他 goroutine 的 panic。
1
2
3
4
5
6
7
8
9
10
11
12
|
func mayPanic() {
panic(\"a problem occurred\")
}
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println(\"Recovered. Error:\", r)
}
}()
mayPanic() // 触发 panic
fmt.Println(\"After mayPanic()\") // 不会执行
}
|
4. 错误处理建议
- 优先返回 error:常规错误应通过多返回值(如 error 类型)处理。
- 谨慎使用 panic:仅在严重错误或不可恢复场景下使用(如程序启动失败)。
- 在关键位置 recover:例如在 goroutine 的入口或 HTTP 请求处理器中,防止程序崩溃。
Web 服务器示例:
1
2
3
4
5
6
7
8
|
func handleRequest() {
defer func() {
if err := recover(); err != nil {
log.Println(\"Request failed:\", err)
}
}()
// 处理请求逻辑(可能触发 panic)
}
|
5. 常见错误场景
- 未捕获的 panic:若未在 defer 中调用 recover,程序会崩溃。
- 跨 goroutine panic:每个 goroutine 需独立处理自己的 panic。
总结
- panic:用于终止程序执行并传递错误信息。
- recover:在 defer 中捕获 panic,恢复程序流程。
- 最佳实践:优先使用错误返回值,仅在必要时结合 panic 和 recover。
通过合理使用这两个关键字,可以提升程序的健壮性,避免因未处理异常导致的崩溃。
|