Go语言追求简洁优雅,因此,Go语言不支持传统的 try…catch…finally 这种异常,由于Go语言的设计者们认为,将异常与控制结构混在一块儿会很容易使得代码变得混乱。由于开发者很容易滥用异常,甚至一个小小的错误都抛出一个异常。在Go语言中,使用多值返回来返回错误。不要用异常代替错误,更不要用来控制流程。在极个别的状况下,也就是说,遇到真正的异常的状况下(好比除数为0了)。才使用Go中引入的Exception处理:defer, panic, recover。app
这几个异常的使用场景能够这么简单描述:Go中能够抛出一个panic的异常,而后在defer中经过recover捕获这个异常,而后正常处理。函数
例子代码:spa
package main.net
import "fmt"设计
func main(){code
defer func(){ // 必需要先声明defer,不然不能捕获到panic异常orm
fmt.Println("c")对象
if err:=recover();err!=nil{blog
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
exit code 0, process exited normally.
参考: http://blog.csdn.net/ghost911_slb/article/details/7831574
defer
defer 英文原意: vi. 推迟;延期;服从 vt. 使推迟;使延期。
defer的思想相似于C++中的析构函数,不过Go语言中“析构”的不是对象,而是函数,defer就是用来添加函数结束时执行的语句。注意这里强调的是添加,而不是指定,由于不一样于C++中的析构函数是静态的,Go中的defer是动态的。
func f() (result int) {
deferfunc()
{
result++
}()
return0
}
上面函数返回1,由于defer中添加了一个函数,在函数返回前改变了命名返回值的值。是否是很好用呢。可是,要注意的是,若是咱们的defer语句没有执行,那么defer的函数就不会添加,若是把上面的程序改为这样:
func f() (result int) {
return0
deferfunc()
{
result++
}()
return0
}
上面的函数就返回0了,由于还没来得及添加defer的东西,函数就返回了。
另外值得一提的是,defer能够屡次,这样造成一个defer栈,后defer的语句在函数返回时将先被调用。
参考: http://weager.sinaapp.com/?p=31
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实现相似 try catch 的异常处理有个例子在:
[plain] view plaincopy
package main
//实现 try catch 例子
func Try(fun func(), handler func(interface{})) {
defer func() {
if err := recover(); err != nil {
handler(err)
}
}()
fun()
}
func main() {
Try(func() {
panic("foo")
}, func(e interface{}) {
print(e)
})
}
结论:
Go对待异常(准确的说是panic)的态度就是这样,没有全面否认异常的存在,同时极力不鼓励多用异常。