...

パッケージ errors

import "errors"
概要
目次

概要 ▾

errors パッケージはエラーを操作する関数を提供します。

New 関数は,中身がテキストメッセージのみであるエラーを作成します。

Unwrap, Is, および As 関数は,他のエラーをラップする可能性のあるエラーに対して機能します。 エラーの型に以下のメソッドがある場合,エラーは別のエラーをラップします

Unwrap() error

e.Unwrap() が nil でないエラー w を返す時, e は w をラップすると言います。

ラップされたエラーを作成する簡単な方法は, %w 動詞をエラー引数にして fmt.Errorf を呼び出すことです。

fmt.Errorf("... %w ...", ..., err, ...).Unwrap()

は err を返します。

Unwrap は,ラップされたエラーをアンパックします。 引数の型に Unwrap メソッドがある場合,メソッドを 1 回呼び出します。 それ以外の場合は, nil を返します。

Is は,最初の引数をアンラップして, 2 番目に一致するエラーを順番に探します。 一致が見つかったかどうかを報告します。 単純な同等性チェックよりも優先して使用する必要があります。

if errors.Is(err, os.ErrExist)

は,

if err == os.ErrExist

より優先すべきです。なぜなら, err が os.ErrExist をラップしているなら,前者は成功するからです。

最初の引数をアンラップすると, 2 番目の引数に割り当てることができるエラーを順番に探します。エラーはポインターである必要があります。 成功した場合,割り当てを実行し, true を返します。 それ以外の場合は, false を返します。 フォーム

var perr *os.PathError
if errors.As(err, &perr) {
	fmt.Println(perr.Path)
}

は,

if perr, ok := err.(*os.PathError); ok {
	fmt.Println(perr.Path)
}

より優先すべきです。なぜなら, err が *os.PathError をラップしているなら,前者は成功するからです。

コード:

package errors_test

import (
    "fmt"
    "time"
)

// MyError は時間とメッセージを含んだエラーです
type MyError struct {
    When time.Time
    What string
}

func (e MyError) Error() string {
    return fmt.Sprintf("%v: %v", e.When, e.What)
}

func oops() error {
    return MyError{
        time.Date(1989, 3, 15, 22, 30, 0, 0, time.UTC),
        "the file system has gone away",
    }
}

func Example() {
    if err := oops(); err != nil {
        fmt.Println(err)
    }
    // Output: 1989-03-15 22:30:00 +0000 UTC: the file system has gone away
}

func As 1.13

func As(err error, target interface{}) bool

As は,err のチェーン内で target に一致する最初のエラーを検出し,検出された場合, target をそのエラー値に設定し, true を返します。

チェーンは, err 自体と,それに続く Unwrap の繰り返し呼び出しによって取得されるエラーのシーケンスで構成されます。

エラーの具体的な値が target が指す値に割り当て可能な場合,またはエラーに As(target) が true を返す As(interface {}) bool メソッドがある場合,エラーは target に一致します。 後者の場合, As メソッドが target の設定をおこないます。

target がエラーを実装する型または任意のインターフェース型への非 nil ポインターでない場合,パニックします。 err が nil の場合, As は false を返します。

コード:

if _, err := os.Open("non-existing"); err != nil {
    var pathError *os.PathError
    if errors.As(err, &pathError) {
        fmt.Println("Failed at path:", pathError.Path)
    } else {
        fmt.Println(err)
    }
}

出力:

Failed at path: non-existing

func Is 1.13

func Is(err, target error) bool

Is は, err のチェーン内のエラーが target と一致するかどうかを報告します。

チェーンは, err 自体と,それに続く Unwrap の繰り返し呼び出しによって取得されるエラーのシーケンスで構成されます。

エラーは, target と等しい場合,または Is(target) が true を返すメソッド Is(error)bool メソッドを実装している場合, target に一致すると見なされます。

func New

func New(text string) error

New は,渡されたテキストを表示するエラーを返します。 text が同一であったとしても,New の呼び出しは毎回異なるエラー値を返します。

コード:

err := errors.New("emit macho dwarf: elf header corrupted")
if err != nil {
    fmt.Print(err)
}

出力:

emit macho dwarf: elf header corrupted

例 (Errorf)

The fmt パッケージの Errorf 関数を使うと,fmt パッケージのフォーマットを使って 詳細なエラーメッセージを作成することができます。

コード:

const name, id = "bimmler", 17
err := fmt.Errorf("user %q (id %d) not found", name, id)
if err != nil {
    fmt.Print(err)
}

出力:

user "bimmler" (id 17) not found

func Unwrap 1.13

func Unwrap(err error) error

Unwrap は, err の型にエラーを返す Unwrap メソッドが含まれている場合, err で Unwrap メソッドを呼び出した結果を返します。 それ以外の場合, Unwrap は nil を返します。