如何优雅处理GO异常
go没有php java nodejs python的try catch
和异常捕获有关的几个内置函数
defer 析构,函数结束时候调用
panic 抛出致命错误,同throw
recover 恢复,recover 只能放到 defer 函数里面,不能放到子函数。
go语言中的defer就像c++中的析构函数,但是go语言中defer的对象是函数(或者对象的方法),defer能保证在函数结束最后执行该方法(函数),但是有例外:如果在定义的方法中defer定义的方法如果在panic后面,defer定义的方法就无法执行到。
panic 是用来表示非常严重的不可恢复的错误的。在Go语言中这是一个内置函数,接收一个interface{}类型的值作为参数。panic 的作用就像我们平常接触的异常。不过Go可没有try…catch,所以,panic一般会导致程序挂掉(除非recover)。所以,Go语言中的异 常,那真的是异常了。你可以试试,调用panic看看,程序立马挂掉,然后Go运行时会打印出调用栈。
但是,关键的一点是,即使函数执行的时候 panic了,函数不往下走了,运行时并不是立刻向上传递panic,而是到defer那,等defer的东西都跑完了,panic再向上传递。所以这时候 defer 有点类似 try-catch-finally 中的 finally。
panic的函数并不会立刻返回,而是先defer,再返回,如果有办法将panic捕获到,并阻止panic传递,就正常处理,如果没有没有捕获,程序直接异常终止。
Go语言提供了recover内置函数,前面提到,一旦panic,逻辑就会走到defer那,那我们就在defer那等着,调用recover函 数将会捕获到当前的panic(如果有的话),被捕获到的panic就不会向上传递了,于是,世界恢复了和平。你可以干你想干的事情了。
不过要注意的是,recover之后,逻辑并不会恢复到panic那个点去,函数还是会在defer之后返回。
以上内容来自这里。小马总结一下:
panic或异常抛出 之后 后的代码段是不被执行的。panic异常抛出后先执行了defer“析构”函数(如果有),如果析构函数有recover函数捕获异常,则执行捕获处理语句,并继续执行完 析构函数以下的代码段,最后退出程序,结束。不再回到异常点继续执行。如果析构函数没有捕获,则直接再向上抛出异常。如果异常始终不被捕获处理,则程序直接挂掉。
代码例子:
func main(){
defer func(){ // 必须要先声明defer,否则不能捕获到panic异常 。注意:defer 是函数return前执行,类似析构,所以这里是总的函数退出前捕获层层抛出的异常
fmt.Println("c")
if err:=recover();err!=nil{
fmt.Println(err) // 这里的err其实就是panic传入的内容,55
}
fmt.Println("d")
}()
f()
}
func f(){
fmt.Println("a")
panic(55)
fmt.Println("b")
fmt.Println("f")
}
输出结果:
a
c
55
d