Go開發(fā)工程師
未來3-5年企業(yè)高性能項目不可替代的語言,從基礎(chǔ)到項目實戰(zhàn)再到重構(gòu),真正從入門到精通
在上一節(jié),我們已經(jīng)了解到了足夠多的error
接口及其周邊的知識。現(xiàn)在,是學習另外一種異常處理方式的時候了。先來展示一個名詞——panic
。panic
可被意譯為運行時恐慌。因為它只有在程序運行的時候才會被“拋出來”。并且,恐慌是會被擴散的。當有運行時恐慌發(fā)生時,它會被迅速地向調(diào)用棧的上層傳遞。如果我們不顯式地處理它的話,程序的運行瞬間就會被終止。這里有一個專有名詞——程序崩潰。內(nèi)建函數(shù)panic
可以讓我們?nèi)藶榈禺a(chǎn)生一個運行時恐慌。不過,這種致命錯誤是可以被恢復的。在Go語言中,內(nèi)建函數(shù)recover
就可以做到這一點。
實際上,內(nèi)建函數(shù)panic
和recover
是天生的一對。前者用于產(chǎn)生運行時恐慌,而后者用于“恢復”它。不過要注意,recover
函數(shù)必須要在defer
語句中調(diào)用才有效。因為一旦有運行時恐慌發(fā)生,當前函數(shù)以及在調(diào)用棧上的所有代碼都是失去對流程的控制權(quán)。只有defer
語句攜帶的函數(shù)中的代碼才可能在運行時恐慌迅速向調(diào)用棧上層蔓延時“攔截到”它。這里有一個可以起到此作用的defer
語句的示例:
defer func() { if p := recover(); p != nil { fmt.Printf("Fatal error: %s\n", p) } }()
在這條defer
語句中,我們調(diào)用了recover
函數(shù)。該函數(shù)會返回一個interface{}
類型的值。還記得嗎?interface{}
代表空接口。Go語言中的任何類型都是它的實現(xiàn)類型。我們把這個值賦給了變量p
。如果p
不為nil
,那么就說明當前確有運行時恐慌發(fā)生。這時我們需根據(jù)情況做相應(yīng)處理。注意,一旦defer
語句中的recover
函數(shù)調(diào)用被執(zhí)行了,運行時恐慌就會被恢復,不論我們是否進行了后續(xù)處理。所以,我們一定不要只“攔截”不處理。
我們下面來反觀panic
函數(shù)。該函數(shù)可接受一個interface{}
類型的值作為其參數(shù)。也就是說,我們可以在調(diào)用panic
函數(shù)的時候可以傳入任何類型的值。不過,我建議大家在這里只傳入error
類型的值。這樣它表達的語義才是精確的。更重要的是,當我們調(diào)用recover
函數(shù)來“恢復”由于調(diào)用panic
函數(shù)而引發(fā)的運行時恐慌的時候,得到的值正是調(diào)用后者時傳給它的那個參數(shù)。因此,有這樣一個約定是很有必要的。
總之,運行時恐慌代表程序運行過程中的致命錯誤。我們只應(yīng)該在必要的時候引發(fā)它。人為引發(fā)運行時恐慌的方式是調(diào)用panic
函數(shù)。recover
函數(shù)是我們常會用到的。因為在通常情況下,我們肯定不想因為運行時恐慌的意外發(fā)生而使程序崩潰。最后,在“恢復”運行時恐慌的時候,大家一定要注意處理措施的得當。
命令源碼文件index.go中有三個函數(shù):main
、outerFunc
和innerFunc
。在innerFunc
函數(shù)中,我準備通過調(diào)用panic
函數(shù)引發(fā)一個運行時恐慌。請你在文件中的適當位置添加一條defer
語句,以使得該運行時恐慌得到“恢復”。并且,該文件的運行應(yīng)該使標準輸出上打印出:
Enter main Enter outerFunc Enter innerFunc Fatal error: Occur a panic!
應(yīng)該在main
函數(shù)的開始處添加:
defer func() { if p := recover(); p != nil { fmt.Printf("Fatal error: %s\n", p) } }()
請驗證,完成請求
由于請求次數(shù)過多,請先驗證,完成再次請求
打開微信掃碼自動綁定
綁定后可得到
使用 Ctrl+D 可將課程添加到書簽
舉報