15.2 Panic

在Go语言中 panic() 是一个内置函数,用来表示非常严重的不可恢复的错误。

必须要先声明defer,否则不能捕获到异常。普通函数在执行的时候发生了异常,则开始运行defer(如有),defer处理完再返回。

在多层嵌套的函数调用中调用 panic(),可以马上中止当前函数的执行,所有的 defer 语句都会保证执行并把控制权交还给接收到异常的函数调用者。这样向上冒泡直到最顶层,并执行(每层的) defer,在栈顶处程序崩溃,并在命令行中用传给异常的值报告错误情况:这个终止过程就是 panicking。

一般不要随意用 panic() 中止程序,必须尽力补救错误让程序能继续执行。

自定义包中的错误处理和 panicking,这是所有自定义包实现者应该遵守的最佳实践:

  1. 在包内部,总是应该从异常中 recover:不允许显式的超出包范围的 panic()
  2. 向包的调用者返回错误值。

recover() 函数的调用仅当它在 defer 函数中被直接调用时才有效。下面主函数捕获了异常:

package main
import (
	"fmt"
)
func div(a, b int) {
	defer func() {
		if r := recover(); r != nil {
			fmt.Printf("捕获到异常:%s\n", r)
		}
	}()
	if b < 0 {
		panic("除数需要大于0")
	}
	fmt.Println("余数为:", a/b)
}
func main() {
	// 捕捉内部的异常
	div(10, 0)
	// 捕捉主动的异常
	div(10, -1)
}
程序输出:
捕获到异常:runtime error: integer divide by zero
捕获到异常:除数需要大于0
下一节:recover() 这个内建函数被用于从异常或错误场景中恢复:让程序可以从 panicking 重新获得控制权,停止终止过程进而恢复正常执行。