Go异常处理

首先很抱歉,由于搬家,最近太多事情要处理,导致文章更新比较慢。

这篇文章,我们讲Go中的异常处理。

Go提供了两个内置函数 panic()和recover()用于异常处理。

Go中,对异常处理的整体原则是:多用errors包,少用panic。

对于可预见的错误,比如网络连接失败等,一般都使用errors,只有重大错误才会使用panic。

 

记住一个大原则:panic会导致程序直接挂掉,除非调用了recover方法。

 

在函数内部调用 panic 会立即终止当前函数的执行,由当前调用栈逐层返回,一直到最顶层的 main 函数或是被某一层的 recover 捕捉到。

 

看例子:

package main

 

import (

"fmt"

)

 

func main() {

fmt.Println("Start main")

sub()

fmt.Println("End main")

}

 

func sub() {

fmt.Println("Before panic")

panic("golang_everyday")

fmt.Println("After panic")

}

执行结果:

Start main

Before panic

panic: golang_everyday

 

goroutine 1 [running]:

main.sub()

/Users/baiyuxiong/go/src/baiyuxiong.com/demo/panic.go:18 +0x124

main.main()

/Users/baiyuxiong/go/src/baiyuxiong.com/demo/panic.go:10 +0xdf

 

goroutine 2 [runnable]:

runtime.forcegchelper()

/usr/local/go/src/runtime/proc.go:90

runtime.goexit()

/usr/local/go/src/runtime/asm_amd64.s:2232 +0x1

 

goroutine 3 [runnable]:

runtime.bgsweep()

/usr/local/go/src/runtime/mgc0.go:82

runtime.goexit()

/usr/local/go/src/runtime/asm_amd64.s:2232 +0x1

 

goroutine 4 [runnable]:

runtime.runfinq()

/usr/local/go/src/runtime/malloc.go:712

runtime.goexit()

/usr/local/go/src/runtime/asm_amd64.s:2232 +0x1

exit status 2

可以看到,panic之后,程序停止继续执行,一层层的退出直到main,退出了整个程序,然后打印了堆栈信息。

如果我们在sub函数中,使用defer进行recover:

package main

 

import (

"fmt"

)

 

func main() {

fmt.Println("Start main")

sub()

fmt.Println("End main")

}

 

func sub() {

defer handler()

 

fmt.Println("Before panic")

panic("golang_everyday")

fmt.Println("After panic")

}

 

func handler() {

if err := recover(); err != nil {

fmt.Println("recover msg: ", err)

} else {

fmt.Println("recover ok")

}

}

 

执行结果:

Start main

Before panic

recover msg: golang_everyday

End main

可以看到,sub函数没有执行完,panic后执行了defer就返回到上层main函数了,但是main函数执行结束了。

这是因为recover阻止了异常的继续传播。他将panic限制在了一定的范围内。

 

这就像屋子里丢了一炸弹(panic产生了),本来所有人都要挂掉的(panic传递到main,整个程序退出),但是有一个叫recover的小伙子非常勇敢,duang!!!抱到炸弹上去了,损失就控制在一定范围内了,如果这小伙子越早的抱到炸弹,受伤的人就会越少。

posted @ 2015-08-30 15:32  klain  阅读(4308)  评论(0编辑  收藏  举报