Go沒有像Java那樣的異常機制,它不能拋出異常。因為設計者們認為,將異常與控制結構混在一起容易使得代碼變得混亂。於是乎引入Exception處理: defer,panic,recover;
簡單描述:Go中可以拋出一個panic的異常,然后在defer中通過recover捕獲這個異常,然后正常處理。
例子代碼:
package main
import "fmt"
func demo(){
fmt.Println("Welcome, my name is fudomine")
panic(400)
fmt.Println("Hello")
}
func main(){
defer func(){
fmt.Println("defer start")
errorMsg := recover()
fmt.Println("Error msg :", errorMsg)
fmt.Println("defer end")
}()
demo()
}
運行結果
defer
defer 英文原意: vi. 推遲;延期;服從 vt. 使推遲;使延期。
- Go語言中內置函數;類似於C/PHP的析構函數,但它不是針對對象而是函數;
- 允許在函數中添加多個defer語句。當函數執行到最后時,這些defer語句會按照逆序執行,最后該函數返回(類似堆棧,先進后出)。
- 調用時須在程序結束前調用,簡單來說讓defer語句在return/panic前寫入至內存中;
func demo()(str string){
str = "Hello"
defer func() {
str = "Welcome, my name is fudomine"
}()
return
}
返回結果:Welcome, my name is fudomine
func demo()(str string){
str = "Hello"
return
defer func() {
str = "Welcome, my name is fudomine"
}()
return
}
返回結果:Hello
可能會有小伙伴自己編寫代碼后,答案不一致;為此特貼出不一樣結果的例子代碼並進行分析;
func demo()(string){
str := "Hello"
defer func() {
str = "Welcome, my name is fudomine"
}()
return str
}
原因:defer 中return xxx這一條語句並不是一條原子指令,而上面結果是因為初始化時候就聲明輸出類型是*T(指針);
拆分為:
- 返回值 = xxx
- 調用defer函數
- 空的return
詳細請參考下《深入解析GO》一文
panic
panic 英文原意:n. 恐慌,驚慌;大恐慌 adj. 恐慌的;沒有理由的 vt. 使恐慌 vi. 十分驚慌
- Go是一個內建函數,可以中斷原有的控制流程,進入一個異常的流程中。當函數 Func 調用 panic ,函數Func 的執行被中斷,但是 Func 中的延遲函數會正常執行,然后Func 返回到調用它的地方。在調用的地方, Func 的行為就像調用了 panic 。這一過程繼續向上(只有剛才defer寸在內存中,將會被調用),直到發生 panic 的 goroutine 中所有調用的函數返回,此時程序退出。
recover
recover 英文原意: vt. 恢復;彌補;重新獲得 vi. 恢復;勝訴;重新得球 n. 還原至預備姿勢
- Go是一個內建的函數,可以讓進入令人恐慌的流程中的 goroutine 恢復過來。 recover 僅在延遲函數中有效。在正常的執行過程中,調用 recover 會返回 nil ,並且沒有其它任何效果。如果當前的 goroutine 陷入恐慌,調用recover 可以捕獲到 panic 的輸入值,並且恢復正常的執行。
參考文獻
《go web編程》
作者:不動峰
博客園:http://www.cnblogs.com/mylly/
版權所有,歡迎保留原文鏈接進行轉載:)