🙅♀️
【Golang】カスタムエラー 前編
最近某pomeさんにありがたいコードレビューをいただいているので復習と発信のために残します
logに関するお話は後編で
Goのエラーライブラリについて
- Go言語は、関数やメソッドの戻り値としてerrorインターフェースを実装したオブジェクトをreturnすることで、エラーの発生を呼び出し元に伝える仕組み。
- 呼び出しもとでは、そのエラーをされにreturnすることによって、呼び出しもとを辿ってエラーをreturnする。最終的にプログラムが実行された場所まで戻ることが可能。
pkg/errorsはスタックトレース機能付き
- errorパッケージは単体でもできるが、スタックトレース機能が付いてない。
pkg/errorsを利用するとスタックトレースが出力できる。
でも限界がある
まず、ログとして出力するエラーの種類には以下がある
- ログレベル
- ユーザーID
- エラーが発生した時刻(ログの出力時刻)
- エラーコード
- エラーメッセージ
- スタックトレース
- クライアントがHTTPリクエストをリトライできるかどうか
- 特定のページにリダイレクトが必要かどうか
上記のようにさまざまな情報をログとして出力するが、plg/errorで全て扱えるわけではないので、カスタムエラーを自作する手もある。
カスタムエラーについて
errorが発生した箇所でreasonやstatuscode渡し、
//error用のpayload的なものを作ってる
//codeをdetailに変換
type Kind string
type Code struct {
Kind Kind
Code string
MessageForEndUser string
}
func NewMessage(c Code, format string, val ...interface{}) Detail {
return Detail{
code: c,
messageForDeveloper: fmt.Sprintf(format, val...),
}
}
//引数に上のNewMessageを入れるとerror型で返せる
//detailをerrorに変換
type Error struct {
details []Detail
err error
frames *runtime.Frames
}
//stringを返すErrorというメソッドを実装している(★)
//→エラーインターフェースを実装している
func (e *Error) Error() string {
//ちょめちょめ
}
type Detail struct {
code Code
messageForDeveloper string
}
func NewError(m ...Detail) error {
return newError(nil, m...)
}
func newError(err error, m ...Detail) error {
return &Error{
details: m,
err: err,
frames: newFrames(),
}
}
ちなみにエラーインターフェースはこちら
type error interface {
Error() string
}
使う時
//NewErrorの第一引数がcodeで、そのkeyを渡すことでkindもcodeもmessageも渡せてる
apperror.NewError(apperror.NewMessage(apperror.CodeNotFound, “ss”))
★の部分にもあるとおり、stringを返すError()メソッドを実装(エラーインターフェース)を実装してれば、戻りその構造体はerror型にできる。
Discussion