Skip to content

Instantly share code, notes, and snippets.

@hakamata-rui
Last active December 1, 2017 03:01
Show Gist options
  • Save hakamata-rui/17baa6508baa0dafe8e3c41df05d261a to your computer and use it in GitHub Desktop.
Save hakamata-rui/17baa6508baa0dafe8e3c41df05d261a to your computer and use it in GitHub Desktop.
golangでerrorハンドリングする個人的な最適解
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))
}
@hakamata-rui
Copy link
Author

エラーログを上位関数でまとめて出すか、発生した時点で都度出すか悩んだ。

エラーログの目的はシステムで発生している不具合について開発者にわかりやすく伝えることと定義すると、
エラーをわかりにくくするログはあまり出すべきではないと思う。

エラーログ発生した時点でエラーを出すと、どういったコンテキストでそのエラーを読んだかわからず困りそう。
(例) DBからデータを取るときにDaoでNotFoundのエラーログを多く出していたとして、
Daoの呼び出し元の処理によっては、NotFoundであることを確認する処理もあるはずなので、
DaoでNotFoundをエラーログとして出すのが必ずしも正しいとは言い切れない

ということでエラーログの出力を上位関数に委ねる設計をしたほうが良いと考えてpkg/errorsをつかってそれを実現する。

@hakamata-rui
Copy link
Author

メモ

エラーログの目的
システムで発生している不具合を開発者に「わかりやすく」伝えること

  • 重要度

  • FATAL

  • 見逃せないレベルで対応が必要

  • ERROR

  • 対応が必要

  • WARN

  • 基本的に対応は不要だが、ケースによっては対応が必要

  • 発生時間

  • どのパッケージのどの関数か

  • 関数の呼び出しパラメータ

  • 影響を受けたユーザ

  • NotFound系エラーはシステム側の不具合と断定できないものはWARNに留める

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment