go语言异常的抛出是使用 panic 和 recover 协同处理的,相比于 java 语言的 throws、throw、try、catch、finally, 可以说是非常的少了。
1.panic
panic 是 go 语言的内建函数,为了报告运行期间的错误,该函数用于停止当前的控制流程并引发一个运行时恐慌,可以接受任意类型的参数值,不说通常是 string 或者 error 类型,因为这样更容易描述异常的详细信息。
代码片段
.
// Test functions
func main() {
execute()
}
func execute() {
fmt.Println("函数执行:")
for i := 0;i<=10 ;i++ {
if(i==3){
panic(errors.New("Code exception!"))
}
fmt.Println("执行第:",i," 次",)
}
}
当我们调用 execute 函数中的 panic 函数时,execute 函数会被停止,运行时恐慌就这样沿着调用栈反方向进行传播,来到 main 函数,直到到达当前 goroutine 的调用栈的最顶层。一旦到达顶层(这里只写了main函数调用),也就意味着所有函数的执行都已经被停止,程序已然崩溃。
运行时恐慌并不全是通过调用 panic 函数引发的,也可以是 go 的运行时异常引发。列如下面片段:
代码片段
.
myindex := 5
length := [4]int{2,3,5}
_=length[myindex]
当执行到第三行的时候会引发一个运行时恐慌,是因为它造成了一个数组下标越界的运行时错误,就是由 go 的运行时系统报告的,就相当于我们显示的调用 panic 函数并传入一个 runtime.Error 类型的参数值。runtime.Error 是一个接口类型,内嵌了 go 内置的 error 接口。
显然,我们不希望程序崩溃,那么,我们如何拦截一个运行时恐慌那?
2.recover
运行时恐慌一旦被引发,就会沿着调用方传播直至程序崩溃。go 提供了专用于拦截运行时恐慌的内置函数 recover,它可以使当前的程序从恐慌的状态中恢复并重新获得流程的控制权。recover 函数被调用后,会返回一个 interface{} 类型的结果,如果当前程序正处于运行时恐慌,那么这个结果就是非 nil 的。
代码片段
.
// Test functions
defer func(){
if p := recover(); p != nil {
fmt.Printf("Code exception: %s\n",p)
}
}()
使用时应该注意一下两点:
1:可以把运行时恐慌的携带值转换为 error 类型,并当做常规结果返回给调用方。这样既阻止了恐慌的扩散,又传递了引起恐慌的原因。
2:检查运行时恐慌携带值的类型,并根据类型不同做不同的处理,这样可以精确控制程序的错误处理行为。