Lapis Lazuli

technical blog for web developer

【Go】エラー処理にxerrorsを使う

Goでエラー処理する事は頻繁に出てくると思います。
使われるのは大体標準パッケージのerrorsを使う事が多いと思いますが、Goには準標準パッケージとしてxerrorsがあります。
最近使ってみたら良かったので、今回はxerrorsについて書いていきます。

何がメリットなのか

最大の違いはスタックトレース機能がついていることです。
errorsだと、どの関数のどの箇所で落ちたのかがログに残らないのがですが、xerrorsならこれが可能です。
ただ中身の機能的な部分を言うと、エラーをラッパーするだけならerrorsで問題ないので、使うか使わないかの判断基準はスタックトレースが必要かどうかに絞られます。

スタックトレースの使い方

ではまず普通に実行してみましょう。
ひとまずパッケージのインポートをして、簡単なエラーを返す関数を作成します。

package main

import(
    "golang.org/x/xerrors"
    "fmt"
)

func hoge() error {
    return xerrors.New("have error")
}
func main() {
    if err := hoge(); err != nil {
        fmt.Printf("%v", err)
    }
}

これを実行すると

have error

普通にエラー出力されました。
スタックトレースを機能をつけるには、出力部分を下記のようにします。

fmt.Printf("%+v", err)

これを実行すると下記のように発生箇所が分かるようになるので、エラーを追いやすくなります。

have error:main.hoge  /xerrors/sample/sample.go:11

errorsとxerrorsの関係

Go1.13以降はxerrorsの機能がerrorsに取り込まれた為、スタックトレース以外で使うメリットはほぼないです。
Unwrapなども追加されましたので。
それ以前の環境でやっているのなら意味ありますが、おそらく1.13に上げたほうが将来的なコードの保守性的に良いと思います。
ただし、問題がありそうなのは以前からxerrorsを使っていてerrorsに乗り換えるパターン。
fmt.Errorfで%wを使ってエラーのラッピングが出来るようになったが、xerrors.Errorfとは仕様が違ったりするので、そのまま移行するのは大変だったりします。
ほぼerrorsとfmtに機能が取り込まれた今、機能的に十分なら標準を使うべきですね。
その辺りは要件による形になります。