GOLANG的PANIC和RECOVER
2015-04-14 13:52
417 查看
转载:http://0x55aa.sinaapp.com/%E7%AE%97%E6%B3%95-%E7%BC%96%E7%A8%8B/722.html
http://www.cnblogs.com/ghj1976/archive/2013/02/11/2910114.html
Go没有例如像Java那样的异常机制:不能抛出一个异常。作为代替,它使用了panic和recover机制。一定要记得,这应当作为最后的手段被使用,你的代码中应当没有,或者很少的令人恐慌的东西。这是个强大的工具,明智的使用它。那么,应该如何使用它。
Panic
是一个内建函数,可以中断原有的控制流程,进入一个令人恐慌的流程中。当函数F调用panic,函数F的执行被中断,但是F中的延迟函数会正常执行,然后F返回到调用它的地方。在调用的地方,F的行为就像调用了panic。这一过程继续向上,直到发生panic的goroutine中所有调用的函数返回,此时程序退出。恐慌可以直接调用panic产生。也可以由运行时错误产生,例如访问越界的数组。
Recover
是一个内建的函数,可以让进入令人恐慌的流程中的goroutine恢复过来。Recover仅在延迟函数中有效。在正常的执行过程中,调用recover会返回nil,并且没有其他任何效果。如果当前的goroutine陷入恐慌,调用recover可以捕获到panic的输入值,并且恢复正常的执行。
最容易理解就是给个例子,文章里有例子:
执行结果:
D:\go>gorunb.go
@@@beforepanic
defer##
novalueforuser
如上面所说的:
panic在user=”"时,打断了函数的执行,fmt.Print(“!!afterpanic\n”)没有执行。
但函数中的延迟函数会正常执行,打印了”defer##“。然后返回到调用该函数的地方,继续上面的过程。
直到执行完所有函数的defer,退出程序。
Recover可以捕获到panic的值,上面的打印“novalueforuser”。并且恢复正常的执行。
Go语言追求简洁优雅,所以,Go语言不支持传统的try…catch…finally这种异常,因为Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱。因为开发者很容易滥用异常,甚至一个小小的错误都抛出一个异常。在Go语言中,使用多值返回来返回错误。不要用异常代替错误,更不要用来控制流程。在极个别的情况下,也就是说,遇到真正的异常的情况下(比如除数为0了)。才使用Go中引入的Exception处理:defer,panic,recover。
这几个异常的使用场景可以这么简单描述:Go中可以抛出一个panic的异常,然后在defer中通过recover捕获这个异常,然后正常处理。
例子代码:
a
c
55
d
exitcode0,processexitednormally.
panic英文原意:n.恐慌,惊慌;大恐慌adj.恐慌的;没有理由的vt.
使恐慌vi.十分惊慌
panic是用来表示非常严重的不可恢复的错误的。在Go语言中这是一个内置函数,接收一个interface{}类型的值(也就是任何值了)作为参数。panic的作用就像我们平常接触的异常。不过Go可没有try…catch,所以,panic一般会导致程序挂掉(除非recover)。所以,Go语言中的异常,那真的是异常了。你可以试试,调用panic看看,程序立马挂掉,然后Go运行时会打印出调用栈。
但是,关键的一点是,即使函数执行的时候panic了,函数不往下走了,运行时并不是立刻向上传递panic,而是到defer那,等defer的东西都跑完了,panic再向上传递。所以这时候defer有点类似try-catch-finally中的finally。
panic就是这么简单。抛出个真正意义上的异常。
recover英文原意:vt.恢复;弥补;重新获得vi.恢复;胜诉;重新得球
n.还原至预备姿势
上面说到,panic的函数并不会立刻返回,而是先defer,再返回。这时候(defer的时候),如果有办法将panic捕获到,并阻止panic传递,那就异常的处理机制就完善了。
Go语言提供了recover内置函数,前面提到,一旦panic,逻辑就会走到defer那,那我们就在defer那等着,调用recover函数将会捕获到当前的panic(如果有的话),被捕获到的panic就不会向上传递了,于是,世界恢复了和平。你可以干你想干的事情了。
不过要注意的是,recover之后,逻辑并不会恢复到panic那个点去,函数还是会在defer之后返回。
用Go实现类似trycatch的异常处理有个例子在:
http://www.douban.com/note/238705941/
结论:
Go对待异常(准确的说是panic)的态度就是这样,没有全面否定异常的存在,同时极力不鼓励多用异常。
Go没有例如像Java那样的异常机制:不能抛出一个异常。作为代替,它使用了panic和recover机制。一定要记得,这应当作为最后的手段被使用,你的代码中应当没有,或者很少的令人恐慌的东西。这是个强大的工具,明智的使用它。那么,应该如何使用它。
Panic
是一个内建函数,可以中断原有的控制流程,进入一个令人恐慌的流程中。当函数F调用panic,函数F的执行被中断,但是F中的延迟函数会正常执行,然后F返回到调用它的地方。在调用的地方,F的行为就像调用了panic。这一过程继续向上,直到发生panic的goroutine中所有调用的函数返回,此时程序退出。恐慌可以直接调用panic产生。也可以由运行时错误产生,例如访问越界的数组。
Recover
是一个内建的函数,可以让进入令人恐慌的流程中的goroutine恢复过来。Recover仅在延迟函数中有效。在正常的执行过程中,调用recover会返回nil,并且没有其他任何效果。如果当前的goroutine陷入恐慌,调用recover可以捕获到panic的输入值,并且恢复正常的执行。
最容易理解就是给个例子,文章里有例子:
packagemain import( "fmt" //"os" ) varuser="" funcinita(){ deferfunc(){ fmt.Print("defer##\n") }() ifuser==""{ fmt.Print("@@@beforepanic\n") panic("novalueforuser\n") fmt.Print("!!afterpanic\n") } } functhrowsPanic(ffunc())(bbool){ deferfunc(){ ifx:=recover();x!=nil{ fmt.Print(x) b=true } }() f() fmt.Print("afterthefuncrun") return } funcmain(){ throwsPanic(inita) } |
D:\go>gorunb.go
@@@beforepanic
defer##
novalueforuser
如上面所说的:
panic在user=”"时,打断了函数的执行,fmt.Print(“!!afterpanic\n”)没有执行。
但函数中的延迟函数会正常执行,打印了”defer##“。然后返回到调用该函数的地方,继续上面的过程。
直到执行完所有函数的defer,退出程序。
Recover可以捕获到panic的值,上面的打印“novalueforuser”。并且恢复正常的执行。
Go语言追求简洁优雅,所以,Go语言不支持传统的try…catch…finally这种异常,因为Go语言的设计者们认为,将异常与控制结构混在一起会很容易使得代码变得混乱。因为开发者很容易滥用异常,甚至一个小小的错误都抛出一个异常。在Go语言中,使用多值返回来返回错误。不要用异常代替错误,更不要用来控制流程。在极个别的情况下,也就是说,遇到真正的异常的情况下(比如除数为0了)。才使用Go中引入的Exception处理:defer,panic,recover。
这几个异常的使用场景可以这么简单描述:Go中可以抛出一个panic的异常,然后在defer中通过recover捕获这个异常,然后正常处理。
例子代码:
packagemain
import"fmt"
funcmain(){
deferfunc(){//必须要先声明defer,否则不能捕获到panic异常
fmt.Println("c")
iferr:=recover();err!=nil{
fmt.Println(err)//这里的err其实就是panic传入的内容,55
}
fmt.Println("d")
}()
f()
}
funcf(){
fmt.Println("a")
panic(55)
fmt.Println("b")
fmt.Println("f")
}
输出结果:
a
c
55
d
exitcode0,processexitednormally.
panic
panic英文原意:n.恐慌,惊慌;大恐慌adj.恐慌的;没有理由的vt.使恐慌vi.十分惊慌
panic是用来表示非常严重的不可恢复的错误的。在Go语言中这是一个内置函数,接收一个interface{}类型的值(也就是任何值了)作为参数。panic的作用就像我们平常接触的异常。不过Go可没有try…catch,所以,panic一般会导致程序挂掉(除非recover)。所以,Go语言中的异常,那真的是异常了。你可以试试,调用panic看看,程序立马挂掉,然后Go运行时会打印出调用栈。
但是,关键的一点是,即使函数执行的时候panic了,函数不往下走了,运行时并不是立刻向上传递panic,而是到defer那,等defer的东西都跑完了,panic再向上传递。所以这时候defer有点类似try-catch-finally中的finally。
panic就是这么简单。抛出个真正意义上的异常。
recover
recover英文原意:vt.恢复;弥补;重新获得vi.恢复;胜诉;重新得球n.还原至预备姿势
上面说到,panic的函数并不会立刻返回,而是先defer,再返回。这时候(defer的时候),如果有办法将panic捕获到,并阻止panic传递,那就异常的处理机制就完善了。
Go语言提供了recover内置函数,前面提到,一旦panic,逻辑就会走到defer那,那我们就在defer那等着,调用recover函数将会捕获到当前的panic(如果有的话),被捕获到的panic就不会向上传递了,于是,世界恢复了和平。你可以干你想干的事情了。
不过要注意的是,recover之后,逻辑并不会恢复到panic那个点去,函数还是会在defer之后返回。
用Go实现类似trycatch的异常处理有个例子在:
结论:
Go对待异常(准确的说是panic)的态度就是这样,没有全面否定异常的存在,同时极力不鼓励多用异常。
相关文章推荐
- golang 使用defer、panic、recover的问题
- golang panic recover
- Golang异常处理-panic与recover
- golang用panic和recover做业务流程中断的尝试
- Golang中的defer, panic, recover
- golang中的defer panic recover
- golang中recover和panic用法
- golang中recover和panic用法
- Golang中的panic和recover
- golang的defer,recover,panic用法
- golang学习的点点滴滴:异常处理 defer, panic, recover
- golang基础-new_make、recover_panic、append、闭包
- golang recover panic 流程控制的可达与不可达
- Golang 中的 panic 与 recover 理解
- 【GoLang】panic defer recover 深入理解
- golang之defer,panic,recover用法
- golang错误处理之panic和recover
- GO_05_2:Golang 中 panic、recover、defer 的用法
- golang panic and recover
- golang 函数-defer-recover-panic