Open5

Goの独自エラーを定義して、複数のエラーを返すようにする

watatakahashiwatatakahashi

Goで独自エラーの定義方法はいくつかある
ここでは構造体で定義する方法をまとめる

まずerrorを直接もたせる方法、超簡単。

type OriginalError struct {
	error
}

もう一つはError()メソッドを定義する。
Goでインターフェースから実装する方法はプロパティ、メソッドを持っているかどうかで判断する。なので他言語のようにimplimentなど書かなくて良い。なので実装が不十分だと定義時ではなく呼び出したときに警告が出る。

type OriginalErrorByFunc struct{}

func (o OriginalErrorByFunc) Error() string {
	return "Errorメソッドを作ることで、errorオブジェクトを自作"
}
watatakahashiwatatakahashi

今回やりたいこと
よくあるのがエラーは関数の第2戻り値で単一エラーを返すが、今回は複数のエラーをまとめて画面に渡す想定

watatakahashiwatatakahashi

定義側
複数のエラーを格納できるOriginalErrorListを定義する
そして独自エラーオブジェクトから専用のエラー、ここではエラーABCを作る

type OriginalError struct {
	error
}

type OriginalErrorList struct {
	error
	items []OriginalError
}

var (
	ErrorA = OriginalError{errors.New("エラーA")}
	ErrorB = OriginalError{errors.New("エラーB")}
	ErrorC = OriginalError{errors.New("エラーC")}
)
watatakahashiwatatakahashi

使う側
エラーメッセージは使う側で決めてあげる。ここではoriginalErrorToMessageをつかってエラーの種別ごとにマッピングできるようにした
OriginalErrorが発生しうる関数someFuncがあるとする

mainで実行するとsomeFuncでエラー一覧を受け取り、メッセージに変換して表示する作り。

var originalErrorToMessage = map[OriginalError]string{
	ErrorA: "エラーAが発生しました",
	ErrorB: "エラーBが発生しました",
	ErrorC: "エラーCが発生しました",
}

func someFunc() OriginalErrorList {
	// エラーA,Bが発生したとする
	return OriginalErrorList{items: []OriginalError{ErrorA, ErrorB}}
}

func main() {
	errList := someFunc()

	for _, item := range errList.items {
		message, ok := originalErrorToMessage[item]
		if !ok {
			// キーが見つからない場合
		}
		fmt.Println(message)
	}
}
watatakahashiwatatakahashi

OriginalErrorListはわざわざエラーinterfaceから実装しなくていいような気もするが?

ここにはエラー概要を入れてエラー詳細をOriginalErrorに持たせれば意味はありそう。
あとはさらにエラーを呼び出し元に返す使い方をする場合を考えると、エラーオブジェクトとして返せなくなるのでそれならあったほうが良いか。

type OriginalErrorList struct {
        error //<-いる?
	items []OriginalError
}