LoginSignup
72
44

More than 5 years have passed since last update.

Goでエラーのスタックトレースを追える&表示する方法

Last updated at Posted at 2017-07-23

errorsパッケージの代わりにgithub.com/pkg/errorsを使うと良いです。

自分でerrors.New()しているところ

今から修正するとして、自分でerrors.New()しているところについて、やることはこれだけ。

  • errorsの代わりにgithub.com/pkg/errorsをimportする
  • 従来通りerrors.New()でエラーを生成する
    • github.com/pkg/errorsを使用しているが、errors.New()の記述は一緒なので修正する必要なし
  • エラーハンドラなどスタックトレースを表示したいところで、フォーマット文字列に%+vを使う

サンプルコード

package main

import (
    "fmt"
    "github.com/pkg/errors"
)

func main() {
    err := level1()
    fmt.Printf("error %+v\n", err)
}

func level1() error {
    return level2()
}

func level2() error {
    return level3()
}

func level3() error {
    return errors.New("level3で発生したエラーです")
}

実行結果

error level3で発生したエラーです
main.level3
    /xxx/error.go:22 <-- errors.New()した行
main.level2
    /xxx/error.go:18
main.level1
    /xxx/error.go:14
main.main
    /xxx/error.go:9
runtime.main
    /xxx/proc.go:185
runtime.goexit
    /xxx/asm_amd64.s:2197

fmt.Printfを使って出力していますが、fmt.SprintfでもloggerのPrintfなどでも%+vを使えます!

自分でerrors.New()していないところ

ライブラリの戻り値など自分でerrors.New()していないところは、errors.WithStack()を使ってerrorをスタックトレース付きのものにラッピングして返すと良いです。

package main

import (
    "fmt"
    "github.com/pkg/errors"
    "strconv"
)

func main() {
    err := level1()
    fmt.Printf("error %+v\n", err)
}

func level1() error {
    return level2()
}

func level2() error {
    return level3()
}

func level3() error {
    // 失敗するParse
    _, err := strconv.ParseBool("XXX")
    return errors.WithStack(err)
}

実行結果。errors.WithStack()したところまでたどれる。

error strconv.ParseBool: parsing "XXX": invalid syntax
main.level3
    /xxx/error.go:25 <-- errors.WithStack()した行
main.level2
    /xxx/error.go:19
main.level1
    /xxx/error.go:15
main.main
    /xxx/error.go:10
runtime.main
    /usr/local/Cellar/go/1.8.3/libexec/src/runtime/proc.go:185
runtime.goexit
    /usr/local/Cellar/go/1.8.3/libexec/src/runtime/asm_amd64.s:2197

まとめ

  • 標準のerrorsではなく、github.com/pkg/errorsをimportする
  • errors.New()は、今まで通り
  • 他のライブラリが返すerrorはerrors.WithStack(error)でラップして返す
  • エラーハンドラで"%+v"を使って、スタックトレースを含めたエラー表示なり、ログ出力ナリする

これでエラーを追いやすくなりますね!

72
44
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
72
44