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。

#Go