エラーパッケージを作った話です。
私は、上記のエントリの「ぼくがかんがえるエラー処理の要件」に完全同意*1で、パフォーマンスをある程度犠牲にしてでもスタックトレースを「カジュアルに」受け取りたいと考えています。
また、
にもあるように「移行のしやすさ」も欲しいです。
というのも、
にあるように、将来的にGoの標準パッケージにスタックトレースを取得できる機能が登場する可能性があるからです。標準パッケージ最高。
で、
に「独自に実装するのもおすすめ」とあったので、既存のエラーパッケージを参考に独自に実装してみました。
github.com/k1LoW/errors
特徴としては次のとおりです。
import "errors"
をimport "github.com/k1LoW/errors"
に書き換えてすぐに使用できる- もともと
errors
パッケージが持つ関数の挙動は一切変えていない(ただのラッパー。errors.New でスタックトレースを取得し始めるという挙動もない)。- 今回はリネームしてもらう戦略を選択した( https://github.com/k1LoW/exec と同じ )
- 逆に
github.com/k1LoW/errors
をerrors
に変えるのもすぐ。移行しやすい(はず)
- もともと
- 取得したスタックトレースをできる限り維持する。
- スタックトレースを取得する関数(
WithStack
)を何回重ねてコールしても元のスタックトレースが消えることはない- 名前付き返り値
(error err)
とdefer
を使ったカジュアルなスタックトレース取得が可能
- 名前付き返り値
- errors.Join にも対応(N本のスタックトレースがあればN本保持して出力できる)
- スタックトレースを取得する関数(
- スタックトレースを構造化データに変換できる
- json.Marshal や、 slog.JSONHandler を使用しているときの slog.Any で取得可能
結局、標準パッケージである errors
パッケージに追加した機能は
errors.WithStack(err error)
でスタックトレースを保持して、errors.StackTraces(err error)
でスタックトレースを取得する
だけです。
それだけのパッケージです。現時点では %+v
や %#v
といったverbにも対応していません*2。
シンプルな分、「 github.com/k1LoW/errors
の導入」も「 github.com/k1LoW/errors
からの移行」も楽だと思っています。