Last active
December 1, 2017 03:01
-
-
Save hakamata-rui/17baa6508baa0dafe8e3c41df05d261a to your computer and use it in GitHub Desktop.
golangでerrorハンドリングする個人的な最適解
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"github.com/pkg/errors" | |
) | |
var ( | |
ErrHoge = errors.Errorf("error hoge occur") | |
ErrFuga = errors.Errorf("error fuga occur") | |
) | |
func test_a() error { | |
// エラーが発生した箇所を特定できるようにWithStackする | |
return errors.WithStack(ErrHoge) | |
} | |
func test_b() error { | |
err := test_a() | |
// エラーにコメントをつける場合はWrapする | |
return errors.Wrap(err, "error throw test_b") | |
} | |
func test_c() error { | |
// エラーにコメントなければWithStackで返す | |
// (そのまま返すと上位でpkg/errorsのerrorであるかを確認する必要がある) | |
err := test_b() | |
return errors.WithStack(err) | |
} | |
func test_d() error { | |
// 上位でハンドリングする場合は途中でエラーを変更する | |
err := test_b() | |
if errors.Cause(err) == ErrHoge { | |
// 呼び出し元のコンテキストによってErrFugaをハンドリングしない場合もあるのでエラー発生源では必ずWithStackする | |
return errors.WithStack(ErrFuga) | |
} | |
return err | |
} | |
func main() { | |
err := test_c() | |
// 呼び出し元でハンドリングなし | |
fmt.Println(fmt.Sprintf("ERROR: %+v", err)) | |
// errorの比較は必ずcauseで行う | |
err = errors.Cause(err) | |
fmt.Println(fmt.Sprintf("ERROR CAUSE: %+v", err)) | |
fmt.Println(fmt.Sprintf("ERROR is ErrHoge? %t", ErrHoge == err)) | |
// 呼び出し元でハンドリングあり | |
err = test_d() | |
fmt.Println(fmt.Sprintf("ERROR: %+v", err)) | |
err = errors.Cause(err) | |
fmt.Println(fmt.Sprintf("ERROR CAUSE: %+v", err)) | |
fmt.Println(fmt.Sprintf("ERROR is ErrFuga? %t", ErrFuga == err)) | |
} |
メモ
エラーログの目的
システムで発生している不具合を開発者に「わかりやすく」伝えること
-
重要度
-
FATAL
-
見逃せないレベルで対応が必要
-
ERROR
-
対応が必要
-
WARN
-
基本的に対応は不要だが、ケースによっては対応が必要
-
発生時間
-
どのパッケージのどの関数か
-
関数の呼び出しパラメータ
-
影響を受けたユーザ
-
NotFound系エラーはシステム側の不具合と断定できないものはWARNに留める
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
エラーログを上位関数でまとめて出すか、発生した時点で都度出すか悩んだ。
エラーログの目的はシステムで発生している不具合について開発者にわかりやすく伝えることと定義すると、
エラーをわかりにくくするログはあまり出すべきではないと思う。
エラーログ発生した時点でエラーを出すと、どういったコンテキストでそのエラーを読んだかわからず困りそう。
(例) DBからデータを取るときにDaoでNotFoundのエラーログを多く出していたとして、
Daoの呼び出し元の処理によっては、NotFoundであることを確認する処理もあるはずなので、
DaoでNotFoundをエラーログとして出すのが必ずしも正しいとは言い切れない
ということでエラーログの出力を上位関数に委ねる設計をしたほうが良いと考えてpkg/errorsをつかってそれを実現する。