Go 的錯誤處理策略 筆記

miss201發表於2018-08-15

Go的錯誤處理是採用一個內建的 error 介面來處理:

 // The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
    Error() string
}

error型別的值可能是 nil 或者 non-nil 。nil 意味著函式執行成功,non-nil 表示失敗。對於non-nil 的error型別,我們可以通過呼叫 error 的 Error() 函式或者輸出函式獲得字串型別的錯誤資訊。
如下面程式碼輸出即可:

fmt.Println(err.Error())
fmt.Printf("%v", err)

錯誤處理策略
1.傳播錯誤
意味著函式中某個子程式的失敗,會變成該函式的失敗。

resp, err := http.Get(url)
if err != nil {
return nill, err
}

2.重新嘗試失敗的操作
錯誤的發生是偶然性的,或由不可預知的問題導致的。一個明智的選擇是重新嘗試失敗的操作。在重試時,我們需要限制重試的時間間隔或重試的次數,防止無限次重試。

package main

import (
    "fmt"
    "log"
    "net/http"
    "time"
)

func waitForServer(url string) error {
    const timeout = 1 * time.Minute
    deadline := time.Now().Add(timeout)

    for tries := 1; time.Now().Before(deadline); tries += 1 {
        _, err := http.Get(url)
        if err == nil {
            return nil
        }

        log.Printf("Server not respond (%v);the %d times retry....", err, tries)
        time.Sleep(time.Second * 2)
    }
    return fmt.Errorf("server %v failed to respond,after %s", url, deadline)
}
func main() {
    url := "http://xxxx.com"
    fmt.Println(waitForServer(url))
}

3.輸出錯誤資訊並結束程式
如果錯誤發生後,程式無法繼續執行。我們就可以輸出錯誤並結束程式。需要注意的是,這種策略只應在 main 中執行。

// (In function main.)
if err := WaitForServer(url); err != nil {
    fmt.Fprintf(os.Stderr, "Site is down: %v\n", err)
    os.Exit(1)
     }

4.輸出錯誤資訊不需要中斷程式的執行
這個可以通過 log 包提供的函式實現。

if err := Ping(); err != nil {
    log.Printf("ping failed: %v; networking disabled",err)
    }

或者

if err := Ping(); err != nil {
    fmt.Fprintf(os.Stderr, "ping failed: %v; networking disabled\n", err)
        }

5.直接忽略掉錯誤

dir, err := ioutil.TempDir("", "scratch")
if err != nil {
 return fmt.Errorf("failed to create temp dir: %v",err)
}
// ...use temp dir...
os.RemoveAll(dir) 
// ignore errors; $TMPDIR is cleaned periodically

上面的程式碼儘管 os.RemoveAll 會失敗,但上面的例子並沒有做錯誤處理。這是因為作業系統會定期的清理臨時目錄。正因如此,雖然程式沒有處理錯誤,但程式的邏輯不會因此受到影響。

  • 我們應該在每次函式呼叫後,都養成考慮錯誤處理的習慣,當你決定忽略某個錯誤時,你應該在清晰的記錄下你的意圖*

總結:在Go中,錯誤處理有一套獨特的編碼風格。檢查某個子函式是否失敗後,我們通常將處理失敗的邏輯程式碼放在處理成功的程式碼之前。如果某個錯誤會導致函式返回,那麼成功時的邏輯程式碼不應放在else語句塊中,而應直接放在函式體中。Go中大部分函式的程式碼結構幾乎相同,首先是一系列的初始檢查,防止錯誤發生,之後是函式的實際邏輯。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

不卑不亢,不慌不忙,這才是生活的模樣。

相關文章