panic关键字 | 豆包MarsCode AI刷题

112 阅读3分钟

panic概述

我们的应用程序常常会出现异常,包括由运行时检测到的异常或者应用开发者自己抛出的异常。异常在一些其他语言中,如c++、java,被叫做Exception,主要由抛出异常和捕获异常两部分组成。异常在go语言中,叫做panic,且由panic和recover方法组成,panic用来抛出,recover用来从panic中恢复。

官方文档:panic是go的内置函数,它可以终止程序的正常执行流程并发出panic。比如当函数F调用panic,F的执行将被终止,并返回到调用者。对调用者而言,F就像调用者直接调用了panic。该过程一直跟随堆栈向上,直到当前goroutine中的所有函数都返回,此时程序崩溃。panic可以通过直接调用panic产生。同时也可能由运行时的错误所产生,例如数组越界访问。recover是go语言的内置函数,它的唯一作用是可以从panic中重新控制goroutine的执行。recover必须通过defer来运行。在正常的执行流程中,调用recover将会返回nil且没有什么其他的影响。但是如果当前的goroutine产生了panic,recover将会捕获到panic抛出的信息,同时恢复其正常的执行流程。

  • panic可以令程序崩溃(异常退出)
  • recover可以让程序从panic中恢复,并正常运行
  • 即使单个goroutine中发生了panic,也会使整个进程崩溃
  • recover必须通过defer来运行

panic和defer

defer关键字

defer关键字定义了在当前函数生命周期结束之前触发的一种机制,类似于C++中的析构函数,Java中的final关键字。如在main函数中定义: defer fmt.Println("end"),表示会在main函数结束前输出end。

defer可在同一函数体中定义多个,执行顺序类似压栈,后定义的defer语句先执行。

当同一函数体中同时出现defer语句和return语句时,return语句会先于defer语句执行。

对于函数的命名返回值和匿名返回值,defer语句的表现不同。

defer语句注册要延迟执行的函数时,如若有参数,首先要确定所有参数的值。

defer 和 panic 的关系

panic 起到立即终止程序执行的作用,这意味着它可以在任何时候触发,包括在函数执行结束之前。为了保证程序能够及时释放资源和执行一些必要的清理工作,Go 语言引入了 defer 这个机制,使得函数在退出之前能够先执行一些清理操作。

当一个函数中触发了 panic,它会立即退出,并执行当前函数之前注册的所有 defer 函数。

在实际开发中,defer 和 panic 往往是成对使用的,defer 用于释放资源和执行清理操作,panic 用于处理异常情况。当一个函数需要在退出之前执行多个清理操作时,我们可以在函数开头使用一个 defer 包装函数,并使用 recover() 函数避免函数提前退出。这种写法非常常见,也为我们编写健壮的程序提供了有力的保证。