Go 学习笔记之 Panic 异常
Go 的类型系统会在编译时捕获很多错误,但有些错误只能在运行时检查,如数组访问越界、空指针引用等。这些运行时错误会引起 painc 异常。
当 panic 异常发生时,程序会中断运行,并立即执行在该 goroutine 中被延迟的函数(defer 机制)。随后,程序崩溃并输出日志信息。
日志信息包括 panic value 和函数调用的堆栈跟踪信息。
panic value 通常是某种错误信息。对于每个 goroutine,日志信息中都会有与之相对的,发生 panic 时的函数调用堆栈跟踪信息。
通常,我们不需要再次运行程序去定位问题,日志信息已经提供了足够的诊断依据。
引发 Panic
不是所有的 panic 异常都来自运行时,直接调用内置的 panic 函数也会引发 panic 异常;panic 函数接受任何值作为参数。当某些不应该发生的场景发生时,我们就应该调用 panic。
比如,当程序到达了某条逻辑上不可能到达的路径:
适用场景
虽然 Go 的 panic 机制类似于其他语言的异常,但 panic 的适用场景有一些不同。
由于 panic 会引起程序的崩溃,因此 panic 一般用于严重错误,如程序内部的逻辑不一致。
任何崩溃都表明代码中存在漏洞,所以对于大部分漏洞,我们应该使用 Go 提供的错误机制,而不是 panic,尽量避免程序的崩溃。在健壮的程序中,任何可以预料到的错误,如不正确的输入、错误的配置或是失败的 I/O 操作都应该被优雅的处理,最好的处理方式,就是使用 Go 的错误机制。
Recover 捕获异常
我们可以从异常中恢复,至少我们可以在程序崩溃前,做一些操作。
举个例子,当 web 服务器遇到不可预料的严重问题时,在崩溃前应该将所有的连接关闭;如果不做任何处理,会使得客户端一直处于等待状态。如果 web 服务器还在开发阶段,服务器甚至可以将异常信息反馈到客户端,帮助调试。
如果在 deferred 函数中调用了内置函数 recover,并且定义该 defer 语句的函数发生了 panic 异常,recover 会使程序从 panic 中恢复,并返回 panic value。导致 panic 异常的函数不会继续运行,但能正常返回。在未发生 panic 时调用 recover,recover 会返回 nil。
deferred 函数帮助 Parse 从 panic 中恢复。在 deferred 函数内部,panic value 被附加到错误信息中;并用 err 变量接收错误信息,返回给调用者。我们也可以通过调用 runtime.Stack 往错误信息中添加完整的堆栈调用信息。
版权声明: 本文为 InfoQ 作者【架构精进之路】的原创文章。
原文链接:【http://xie.infoq.cn/article/f49a2152f48f65242301cbdf8】。文章转载请联系作者。
评论