Go 语言 panic 和 recover 详解

panic() 和 recover() 是 Go 语言中用于处理错误的两个重要函数。panic() 函数用于中止程序并引发panic,而 recover() 函数用于捕获panic并恢复程序的执行。

什么是panic和recover?

panic

  • panic() 函数用于中止程序并引发panic。
  • panic() 函数可以接收一个参数,该参数将作为panic的原因。
  • 当发生panic时,程序将停止执行,并开始寻找最近的recover调用。
  • 如果找不到recover调用,程序将打印panic的原因并退出。

recover

  • recover() 函数用于捕获panic并恢复程序的执行。
  • recover() 函数可以接收一个参数,该参数将存储panic的原因。
  • 如果在发生panic时调用了recover,程序将继续执行,并且panic的原因将被存储在recover的第一个参数中。
Go 复制代码
func main() {
    defer func() {
        err := recover()
        if err != nil {
            fmt.Println("panic:", err)
        }
    }()

    panic("hello, panic!")
}

panic 的传播

panic 函数会向上传播到调用它的 goroutine。如果 panic 函数没有被捕获,则会一直向上传播,直到遇到 defer 语句中调用的 recover() 函数,或者程序退出。

注意事项

跨协程失效

panic 和 recover 不能跨协程使用。这意味着在一个协程中发生的panic只能在同一个协程中通过 recover 捕获。如果在一个协程中发生了panic,而在另一个协程中调用了 recover,那么 recover 将无法捕获panic。参考如下代码:

Go 复制代码
func main() {
	defer println("in main")
	go func() {
		defer println("in goroutine")
		panic("")
	}()

	time.Sleep(1 * time.Second)
}

失效的崩溃恢复

如果在一个defer函数中发生了panic,那么该defer函数后面的语句将不会被执行。这意味着在defer函数中使用 recover 来捕获panic是无效的。

Go 复制代码
func main(){
    defer fmt.Println("main....")
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println("panic:", err)
		}
	}()

	panic("hello, panic!")
}

嵌套崩溃

嵌套崩溃是指在一个 goroutine 中调用 panic() 函数,然后在 defer 语句中再次调用 panic() 函数。在这种情况下,panic() 函数会从内向外传播,直到程序崩溃。嵌套崩溃可能会导致程序不可用,因此应避免使用。

Go 复制代码
func multiplePanic() {
	defer fmt.Println("in defer")
	defer func() {
		defer func() {
			panic("panic 3")
		}()
		panic("panic 2")
	}()
	panic("panic 1")
}
相关推荐
念何架构之路几秒前
go-grpc服务端调用链
开发语言·后端·golang
泡海椒4 分钟前
JQuickExcel 大文件排障与调优:从实际路径定位 OOM、临时盘和慢任务
开发语言·数据库·缓存·oracle·excel
羑悻6 分钟前
atomic凭什么线程安全?无锁编程为何有时比锁还慢?C++高并发必懂的原子操作真相!
后端
SamDeepThinking9 分钟前
synchronized 和 lock 有什么区别?
java·后端·面试
m0_5873830015 分钟前
无人自助拼豆系统的全栈开发方案
java·后端·struts·小程序·架构
雪碧透心凉_19 分钟前
PythonWin32API窗口与鼠标操作
开发语言·python·计算机外设
人道领域27 分钟前
【面试八股速通篇01】锁与并发工具
java·开发语言·面试·c#
kimnoic29 分钟前
PHP 8.3 数据库备份失败怎么排查
开发语言·php
bnmoel31 分钟前
C++ 基础入门篇(六)类和对象-第三篇:运算符重载
开发语言·c++·算法·语法·运算符重载
CRMEB系统商城37 分钟前
CRMEB开源商城系统(PHP)v8.0,打造全新AI二开商城底座!
开发语言·人工智能·小程序·开源·php