在通常情况下,函数向其调用方报告错误的方式都是返回一个error类型的值。但是,
当遇到致命错误的时候,很可能会使程序无法继续运行。这时,上述错误处理方式就太
不适合了,Go推荐通过调用panic函数来报告致命错误。
1.panic
为了报告运行期间的致命错误,Go内建了专用函数panic,该函数用于停止当前的
控制流程并引发一个运行时恐慌。它可以接受一个任意类型的参数值,不过这个参数值
的类型常常会是string或者error,因为这样更容易描述运行时恐慌的详细信息。请看下
面的例子:
func main(){outerFunc()}func outerFunc(){innerFunc()}func innerFunc(){panic(errors.New("An intended fatal errorl"))}
当调用innerFunc函数中的panic函数后,innerFunc的执行会被停止。紧接着,流程
控制权会交回给调用方 outerFunc函数。然后,outerFunc函数的执行也将被停止。运行时
恐慌就这样沿着调用栈反方向进行传播,直至到达当前goroutine的调用栈的最顶层。一
旦达到顶层,就意味着该goroutine调用栈中所有函数的执行都已经被停止了,程序已经
崩溃。
当然,运行时恐慌并不都是通过调用panic函数的方式引发的,也可以由Go的运行
时系统来引发。例如:
myIndex:=4ia:=[3]int{1,2,3}_=ia[myIndex]
这个示例中的第3行代码会引发一个运行时恐慌,因为它造成了一个数组访问越界
的运行时错误。这个运行时恐慌就是由Go的运行时系统报告的。它相当于我们显式地调
用panic函数并传入一个runtime.Error类型的参数值。顺便说一句,runtime.Error是一个
接口类型,并且内嵌了Go内置的error接口类型。
显然,我们都不希望程序崩溃。那么,怎样“拦截”一个运行时恐慌呢?
2.recover
运行时恐慌一旦被引发,就会向调用方传播直至程序崩溃。Go提供了专用于“拦截”
运行时恐慌的内建函数recover,它可以使当前的程序从恐慌状态中恢复并重新获得流程
控制权。recover 函数被调用后,会返回一个interface{}类型的结果。如果当时的程序正
处于运行时恐慌的状态,那么这个结果就会是非nil的。
recover 函数应该与defer语句配合起来使用,例如:
defer func(){ifp:=recover();pl=nil{fmt.Printf(“Recovered panic:%s