Go 语言中 panic 和 recover
2025-04-05 444字
panic 和 recover 是用于处理运行时异常的两个内置函数,它们可以互相配合使用来应对程序中未预期的严重错误。
panic
panic 会立即停止当前 goroutine 的执行流程,逐层向上终止函数调用,直至程序崩溃退出。
panic 定义:
func panic(v interface{})
// 参数 v 通常是错误信息,可以是字符串、错误对象等任意类型
示例:
package main
import "fmt"
func main() {
fmt.Println("开始执行")
panic("error")
fmt.Println("结束执行") // 这行不会执行
}
输出:
开始执行
panic: error
goroutine 1 [running]:
main.main()
因为 panic 终止了当前进程,导致整个程序崩溃退出,所以最后一行不会执行。
recover
recover 用于捕获由 panic 引起的异常,从而防止程序奔溃。但是 recover 只在 defer 函数中生效,普通函数中不起作用。
recover 定义:
func recover(v) interface{}
它可以返回任意值,如果当前 goroutine 正在panic,则返回panic时传入的值,否则返回 nil。
示例:
package main
import "fmt"
func main() {
defer func() {
if err := recover(); err != nil {
fmt.Println("recover:", err)
}
}()
fmt.Println("开始执行")
panic("error")
fmt.Println("结束执行") // 这行不会执行
}
输出:
开始执行
recover: panic error
此时 panic 被 recover 捕获了,防止了程序的崩溃。
⚠️注意:recover只对当前 goroutine 有效,意思是说只能捕获同一 goroutine 中的 panic,是不能跨 goroutine 捕获的。例如:
package main
import (
"fmt"
"time"
)
func main() {
defer func() {
if err := recover(); err != nil {
fmt.Println("recover:", err)
}
}()
go func() {
fmt.Println("子线程执行")
panic("子线程错误")
}()
time.Sleep(1 * time.Second)
fmt.Println("主线程执行结束")
}
输出:
子线程执行
panic: 子线程错误
goroutine 7 [running]:
main.main.func2()
该程序崩溃了,因为主线程的 recover 无法捕获子线程中的 panic。