エラーをラップする仕組みが欲しい
ras0q opened this issue · comments
現状convertError
などを使って下位層の具体的なエラーを上位層の抽象的なエラーに変換してレスポンスのステータスコードを決定しているが、下位層のエラーの情報が消えてしまっているのでラップしてログに詳細を吐き出せるようにしたい
util/errorsとかに自前errorsパッケージを定義して↓みたいな感じに実装するとよさそう
package errors
import (
"errors"
"fmt"
)
// 各パッケージのエラーはErrorMessage型で定義する
type ErrorMessage string
type customError struct {
message ErrorMessage
internal error
}
func New(message ErrorMessage) error {
return &customError{
message: message,
}
}
func Wrap(message ErrorMessage, internal error) error {
return &customError{
message: message,
internal: internal,
}
}
// 標準errorsパッケージをラップ
func Is(err, target error) bool {
return errors.Is(err, target)
}
// Errorインターフェイスの実装
func (e *customError) Error() string {
if e.internal != nil {
return fmt.Sprintf("%s: %s", e.message, e.internal.Error())
}
return string(e.message)
}
// 標準errorsパッケージで比較できるようにIsメソッドを実装
// 子エラーは判定には使わないのでUnwrapは実装しなくてもよい
func (e *customError) Is(target error) bool {
if t, ok := target.(*customError); ok {
return e.message == t.message
}
return false
}
- エラーの定義を
errors.New
のvarからErrorMessage
のconstに変える -
echo.NewHTTPError
をするときに.SetInternal
をしてエラーをログに残す
これerrors.Is
で比較するとなるとErrorMessage
とは別に各ErrorMessage
に対してerrors.New
で変数を定義することになって微妙な気がしてきた
errors.Is
を使うのではなくcustomError
とcustomError.message
をpublicにしてerrors.As
で判定してから(ここは型アサーションで十分かも)、messageの種類でswitchで十分かも