天天看點

Golang 中的 errors 包詳解

在 Golang 中,errors 包是用于處理錯誤的标準庫, errors 包提供的功能比較簡單,使用起來非常友善。接下來就具體講解一下 errors 包提供的幾個函數。

errors.New

func New(text string) error           

錯誤處理是開發過程中必不可少的,使用 errors.New 函數可以建立一個表示特定錯誤的對象。接受一個字元串類型的參數(用于描述錯誤資訊),傳回一個 error 類型的值。例如:

package main

import "errors"

func main() {
	err := errors.New("invalid input")
}           

error 類型是 builtin 包中定義的一個接口,定義如下:

type error interface {
	Error() string
}           

可以看出此接口定義了一個基本的 Error 方法,用于傳回錯誤的描述資訊。

package main

import (
	"errors"
	"fmt"
)

func main() {
	err := errors.New("invalid input")
	errDesc := err.Error()
	fmt.Println(errDesc) // 輸出 invalid input
}           

errors.Is

func Is(err, target error) bool           

用于判斷給定的錯誤是否是目标錯誤類型或者基于目标錯誤類型包裝過的錯誤,會遞歸檢查錯誤鍊,直到找到目标錯誤類型或者到達錯誤鍊的末尾。如果找到目标錯誤類型,則傳回true,否則傳回false。看個例子:

package main

import (
	"errors"
	"fmt"
)

func main() {
	err := errors.New("invalid input")
	err1 := errors.New("invalid input")
	err2 := fmt.Errorf("err2: [%w]", err)
	fmt.Println(errors.Is(err1, err)) // false
	fmt.Println(errors.Is(err2, err)) // true
}           

因為 err 和 err1 都是使用 errors.New 函數建立的,是以使用 Is 判斷會傳回 false。err2 是基于 err 包裝出來的,是以使用 Is 判斷會傳回 true。

errors.AS

func As(err error, target any) bool           

用于将錯誤轉換為特定類型的錯誤,As 函數會檢查 err 是否是 target 指向的類型的執行個體,如果是,将該執行個體指派給 target 并傳回 true。否則傳回 false。看個例子:

package main

import (
	"errors"
	"fmt"
)

type MyError struct {
	Message string
}

func (e *MyError) Error() string {
	return e.Message
}
func main() {
	err := &MyError{
		Message: "This is a custom error",
	}
	var target *MyError
	if errors.As(err, &target) {
		fmt.Println("Custom error found:", target.Message)
	} else {
		fmt.Println("Custom error not found")
	}
}           

使用 errors.As 來檢查 err 是否是 MyError 類型的執行個體,并将執行個體指派給 target。運作一下示例看下效果

$ go run main.go
Custom error found: This is a custom error           

這個功能通常用于處理不同類型的錯誤,根據錯誤的類型采取對應的處理方式。

errors.Unwrap

func Unwrap(err error) error           

用于将一個錯誤對象展開,得到下一層錯誤對象,如果錯誤對象沒有下一層錯誤對象,則傳回 nil。看個例子:

package main

import (
	"errors"
	"fmt"
)

func main() {
  originalErr := errors.New("original error")
	err := fmt.Errorf("error: %w", originalErr)
	unwrappedErr := errors.Unwrap(err)
	fmt.Println(unwrappedErr) // 輸出: original error
}           

使用 fmt.Errorf 函數将 originalErr 做了一層包裝後得到 err,然後通過使用 Unwrap 将 err 解包并得包裝前的錯誤對象 originalErr。需要注意的是 Unwrap 隻能展開被 fmt.Errorf 包裝的錯誤對象。如果想要展開其他類型的錯誤對象,可以使用類型斷言操作符 `.` 進行類型斷言。

小結

errors 包提供了一些簡單易用的函數來處理和擷取錯誤資訊,借助 errors 包可以實作非常強大的錯誤處理功能。