進階 Go 範例:錯誤

在 Go 中,慣用的作法是透過明確而獨立的回傳值傳達錯誤。這與 Java 和 Ruby 等語言中所使用的例外機制不同,也不同於 C 中有時會使用的超載單一結果/錯誤值。Go 的作法讓你可以清楚看出哪些函式會回傳錯誤,並使用與其他非錯誤工作相同的語言建構處理這些錯誤。

請參閱 errors 套件這篇部落格文章,以取得更多詳細資訊。

package main
import (
    "errors"
    "fmt"
)

依慣例,錯誤是最後一個回傳值,類型為內建介面 error

func f(arg int) (int, error) {
    if arg == 42 {

errors.New 建構一個基本的 error 值,包含給定的錯誤訊息。

        return -1, errors.New("can't work with 42")
    }

錯誤位置的 nil 值表示沒有錯誤。

    return arg + 3, nil
}

簡易錯誤是一個已宣告的變數,用於表示特定的錯誤狀況。

var ErrOutOfTea = fmt.Errorf("no more tea available")
var ErrPower = fmt.Errorf("can't boil water")
func makeTea(arg int) error {
    if arg == 2 {
        return ErrOutOfTea
    } else if arg == 4 {

我們可以用更高級的錯誤包裝錯誤,以加入脈絡。執行此操作最簡單的方式是使用 fmt.Errorf 中的 %w 關鍵字。包裝錯誤會建立一個邏輯鏈(A 包裝 B,B 包裝 C 等),可以使用 errors.Iserrors.As 等函式查詢這個鏈。

        return fmt.Errorf("making tea: %w", ErrPower)
    }
    return nil
}
func main() {
    for _, i := range []int{7, 42} {

if 行中使用內嵌錯誤檢查是很常見的作法。

        if r, e := f(i); e != nil {
            fmt.Println("f failed:", e)
        } else {
            fmt.Println("f worked:", r)
        }
    }
    for i := range 5 {
        if err := makeTea(i); err != nil {

errors.Is 檢查給定的錯誤(或其鏈中的任何錯誤)是否與特定的錯誤值相符。這在使用包裝錯誤或嵌套錯誤時特別有用,可讓你識別錯誤鏈中的特定錯誤類型或簡易錯誤。

            if errors.Is(err, ErrOutOfTea) {
                fmt.Println("We should buy new tea!")
            } else if errors.Is(err, ErrPower) {
                fmt.Println("Now it is dark.")
            } else {
                fmt.Printf("unknown error: %s\n", err)
            }
            continue
        }
        fmt.Println("Tea is ready!")
    }
}
$ go run errors.go
f worked: 10
f failed: can't work with 42
Tea is ready!
Tea is ready!
We should buy new tea!
Tea is ready!
Now it is dark.

下一個範例:自訂錯誤