#todo #2023/08 時点の知見をまとめたい ## 方針 [[errors.Is]]を使った同値判定のエラーハンドリング。 ```go:main.go package main import ( "errors" "fmt" "github.com/tadashi-aikawa/go-error-handle/lib" ) var ( UserError = errors.New("user error") ServerError = errors.New("server error") ) func errorHandling(x int) error { if err := lib.DoSomething(x); err != nil { switch { case errors.Is(err, lib.ForbiddenError): fallthrough case errors.Is(err, lib.NotFoundError): return UserError case errors.Is(err, lib.InternalServerError): return ServerError } } return nil } func main() { x := 404 if err := errorHandling(x); err != nil { switch { case errors.Is(err, UserError): fmt.Printf("%d はユーザーエラーですね", x) case errors.Is(err, ServerError): fmt.Printf("%d はサーバーエラーですね", x) } } fmt.Println("ok") } ``` ```go:lib/lib.go package lib import "errors" var ( ForbiddenError = errors.New("forbidden") NotFoundError = errors.New("not found error") InternalServerError = errors.New("internal server error") ) func DoSomething(x int) error { switch x { case 403: return ForbiddenError case 404: return NotFoundError case 500: return InternalServerError } return nil } ``` ## メリット - シンプルで直感的 ## デメリット - エラーメッセージが固定になってしまう - スタックトレースは保存されない - [[fmt.Errorf]]などでラップできない 以下の観点からクリティカルな問題ではないはず。 - 関数のインターフェースに渡された値は呼び出し元が知っている - エラーで返却する必要はない - 関数の実装による情報が必要ならログで出した方がいい - 非公開実装を公開インターフェースのエラーメッセージに返すのは不適切 - 比較用に作成するエラーインスタンスで原因は分かるので問題ない ## MOC - [[errors.Isとerrors.Asの違い]]