Go

【Go】エラーラッピングとカスタムエラー

前回はエラー処理の基本を確認しました。

その中でエラーのラッピングとカスタムエラーについても簡単に説明しました。今回はカスタムエラーのラッピングについて確認します。

fmt.Errorf関数でエラーのラッピング

前回のエラー処理の基本でも動作を確認しましたが、fmt.Errorf関数を使用してエラーをラッピングします。errors.Is関数は簡単に言うと受け取ったエラーが想定されるエラーかどうかを判定してくれる関数と思って下さい。

package main

import (
	"errors"
	"fmt"
)

type MyError struct {
}

func (em MyError) Error() string {
	return "俺のエラー!!"
}

func main() {
	// エラーラップする
	reErr := fmt.Errorf("%w", MyError{})

	// 想定通りのエラーである事を確認する
	if errors.Is(reErr, MyError{}) {
		fmt.Println("俺のエラーがあった!!")  // 俺のエラーがあった!! が表示される。
	} else {
		fmt.Println("俺のエラーはない!!")
	}
}

カスタムエラーでラッピング

以下のようにカスタムエラーに他のエラーを保持したい時もあります。しかし、結果は保持しているエラーを確認できません。

package main

import (
	"errors"
	"fmt"
)

type MyError struct {
	err error
}

type orgError struct {
}

func (em MyError) Error() string {
	return "俺のエラー!!"
}

func (em orgError) Error() string {
	return "オリジナルエラー!!"
}

func main() {
	// オリジナルエラーを俺のエラーでラッピングする
	reErr := MyError{err: orgError{}}

	// オリジナルのエラーを確認する
	if errors.Is(reErr, MyError{}) {
		fmt.Println("俺のエラーがあった!!")
	} else {
		fmt.Println("俺のエラーはない!!") // 俺のエラーはない!! が表示される
	}
}

fmt.Errorf関数でラッピングしたエラーはerrors.Is関数で検知できましたが、カスタムエラーでラッピングしたエラーは検知できませんでした。

解決

errors.Is関数の内容

ざっくり言うとerrors.Is関数は第一引数に他から受け取ったエラー、第二引数に想定するエラーを指定します。errors.Is関数は内部で第一引数のエラーに対してUnwrap関数を使用して、第二引数のエラーと比較しています。

fmt.Errorf関数が返すもの

fmt.Errorf関数が返すエラーは、Unwrap関数を実装しています。なのでerrors.Is関数はラッピングされたエラーを検知できます。

具体的な対策

と言うことでerrors.Is関数の第一引数に渡すエラーにUnwrap関数を実装します。

func (em MyError) Unwrap() error {
	return em.err
}

全体的なコードは以下の通りです。

package main

import (
	"errors"
	"fmt"
)

type MyError struct {
	err error
}

type orgError struct {
}

func (em MyError) Error() string {
	return "俺のエラー!!"
}

// 追加
func (em MyError) Unwrap() error {
	return em.err
}

func (em orgError) Error() string {
	return "その他エラー!!"
}

func main() {
	// エラーをラップする
	reErr := MyError{err: orgError{}}

	// オリジナルエラーの存在を確認する
	if errors.Is(reErr, orgError{}) {
		fmt.Println("その他エラーがあった!!") // その他エラーがあった!! が表示される
	} else {
		fmt.Println("その他エラーはない!!")
	}
}

コメントを残す

メールアドレスが公開されることはありません。

© DeNnie.Lab All Rights Reserved.