1. 程式人生 > >【更多流程控制】2. Go語言異常處理——panic

【更多流程控制】2. Go語言異常處理——panic

Go語言異常處理——panic

    在上一節,我們已經瞭解到了足夠多的error介面及其周邊的知識。現在,是學習另外一種異常處理方式的時候了。先來展示一個名詞——panicpanic可被意譯為執行時恐慌。因為它只有在程式執行的時候才會被“丟擲來”。並且,恐慌是會被擴散的。當有執行時恐慌發生時,它會被迅速地向呼叫棧的上層傳遞。如果我們不顯式地處理它的話,程式的執行瞬間就會被終止。這裡有一個專有名詞——程式崩潰。內建函式panic可以讓我們人為地產生一個執行時恐慌。不過,這種致命錯誤是可以被恢復的。在Go語言中,內建函式recover就可以做到這一點。
  
    實際上,內建函式panic

recover是天生的一對。前者用於產生執行時恐慌,而後者用於“恢復”它。不過要注意,recover函式必須要在defer語句中呼叫才有效。因為一旦有執行時恐慌發生,當前函式以及在呼叫棧上的所有程式碼都是失去對流程的控制權。只有defer語句攜帶的函式中的程式碼才可能在執行時恐慌迅速向呼叫棧上層蔓延時“攔截到”它。這裡有一個可以起到此作用的defer語句的示例:

defer func() {
    if p := recover(); p != nil {
        fmt.Printf("Fatal error: %s\n", p)
    }
}()

    在這條defer

語句中,我們呼叫了recover函式。該函式會返回一個interface{}型別的值。還記得嗎?interface{}代表空介面。Go語言中的任何型別都是它的實現型別。我們把這個值賦給了變數p。如果p不為nil,那麼就說明當前確有執行時恐慌發生。這時我們需根據情況做相應處理。注意,一旦defer語句中的recover函式呼叫被執行了,執行時恐慌就會被恢復,不論我們是否進行了後續處理。所以,我們一定不要只“攔截”不處理。
  
    我們下面來反觀panic函式。該函式可接受一個interface{}型別的值作為其引數。也就是說,我們可以在呼叫panic
函式的時候可以傳入任何型別的值。不過,我建議大家在這裡只傳入error型別的值。這樣它表達的語義才是精確的。更重要的是,當我們呼叫recover函式來“恢復”由於呼叫panic函式而引發的執行時恐慌的時候,得到的值正是呼叫後者時傳給它的那個引數。因此,有這樣一個約定是很有必要的。
  
    總之,執行時恐慌代表程式執行過程中的致命錯誤。我們只應該在必要的時候引發它。人為引發執行時恐慌的方式是呼叫panic函式。recover函式是我們常會用到的。因為在通常情況下,我們肯定不想因為執行時恐慌的意外發生而使程式崩潰。最後,在“恢復”執行時恐慌的時候,大家一定要注意處