Goのエラーの生成方法
Go でエラーを生成するときにどのように生成するのがいいのか、少し考えました。
私はエラーを扱うときはたいてい pkg/errors
を使うようにしています。エラーをスタックできるのが便利ですよね。
エラーの起点になるときには fmt.Errorf() や errors.New() でエラーを生成すると思いますが、どちらがよいのでしょうか?
個人的な考え
サンプル実装で考えてみます。どちらも error インターフェースの Error() string
を実装しているので機能としては同等と言えるでしょう。現時点での結論は、errors.New
を使えばいいのでは?と思っています。
package main import ( "fmt" "github.com/pkg/errors" ) func errorByFmtErrorF() error { return fmt.Errorf("Error: %s", "fmt.Errorf") } func errorByErrorsNew() error { return errors.New(fmt.Sprintf("Error: %s", "errors.New")) } func main() { // どちらも error インターフェースを満たしていて、機能としては同等 fmt.Printf("fmt.Errorf: %v\n", errorByFmtErrorF()) fmt.Printf("errors.New: %v\n", errorByErrorsNew()) }
- 出力結果
fmt.Errorf: Error: fmt.Errorf errors.New: Error: errors.New
まぁこのあたりはコードスタイルな気もします。
uber-go の guide にもエラーの扱いが書いてあるので、参考になりそうです。(翻訳版から引用しておきます
uber-style-guide-ja/guide.md at master · knsh14/uber-style-guide-ja · GitHub
- このエラーは追加情報が必要ないか?もし無いなら、errors.New で十分です。
- 利用する側がエラーを検知してハンドリングする必要がありますか?その場合自前で Error() メソッドを実装した型を作る必要があります。
- 下流のエラーを更に上流に返していますか?もしそうなら、section on error wrapping. の章を参考にしてください。
- これらに当てはまらないなら、fmt.Errorf で問題ないでしょう。