Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Goでスタックトレースを扱う方法がややこしい件について

Avatar for syumai syumai
March 26, 2023

 Goでスタックトレースを扱う方法がややこしい件について

Avatar for syumai

syumai

March 26, 2023
Tweet

More Decks by syumai

Other Decks in Programming

Transcript

  1. 自己紹介 syumai Go Documentation 輪読会 / ECMAScript 仕様輪 読会 主催

    Go でGraphQL サーバー (gqlgen) や TypeScript で フロントエンドを書いています Twitter: @__syumai Website: https://syum.ai
  2. 例 func main() { if err := A(); err !=

    nil { fmt.Printf("%v", err) // error! } } func A() error { return B() } func B() error { return errors.New("error!") }
  3. 文言が一緒だと、誰が返したerror かわからない問題 func main() { if err := A(); err

    != nil { fmt.Printf("%v", err) // error! } } func A() error { _ = B() // 握り潰す return C() // 返ってるのは C() の返したerror } func B() error { return errors.New("error!") } func C() error { return errors.New("error!") }
  4. pkg/errors の例 func A() error { return B() } func

    B() error { return pkg_errors.New("error happened") } func main() { err := A() if err != nil { // error happened fmt.Printf("%v\n", err) // error happened // main.B // /Users/syumai/go/src/github.com/syumai/til/go/errors/pkg_errors_example/basic/main.go:14 // main.A // /Users/syumai/go/src/github.com/syumai/til/go/errors/pkg_errors_example/basic/main.go:10 // main.main // /Users/syumai/go/src/github.com/syumai/til/go/errors/pkg_errors_example/basic/main.go:18 // runtime.main // /opt/homebrew/Cellar/go/1.19.5/libexec/src/runtime/proc.go:250 // runtime.goexit // /opt/homebrew/Cellar/go/1.19.5/libexec/src/runtime/asm_arm64.s:1172 fmt.Printf("%+v\n", err) } }
  5. debug.Stack() / debug.PrintStack() func main() { A() } func A()

    { if err := B(); err != nil { debug.PrintStack() // goroutine 1 [running]: // runtime/debug.Stack() // /usr/local/go-faketime/src/runtime/debug/stack.go:24 +0x65 // runtime/debug.PrintStack() // /usr/local/go-faketime/src/runtime/debug/stack.go:16 +0x19 // main.A(...) // /tmp/sandbox4059372707/prog.go:14 // main.main() // /tmp/sandbox4059372707/prog.go:9 +0x18 } } func B() error { return errors.New("error!") } // https://go.dev/play/p/wSqAL9AOviY
  6. runtime.Callers() / runtime.CallersFrames() で書いたprintStack 関数 func printStack() { var pc

    [100]uintptr n := runtime.Callers(0, pc[:]) frames := runtime.CallersFrames(pc[:n]) var ( fr runtime.Frame ok bool ) if _, ok = frames.Next(); !ok { return } for ok { fr, ok = frames.Next() if !ok { return } fmt.Println(fr.Function, fr.File, fr.Line) } } // https://go.dev/play/p/DkGku2xlhSr
  7. 自前のprintStack() 関数を使った様子 func main() { A() } func A() {

    if err := B(); err != nil { printStack() // main.printStack /tmp/sandbox3328056694/prog.go 25 // main.A /tmp/sandbox3328056694/prog.go 15 // main.main /tmp/sandbox3328056694/prog.go 10 // runtime.main /usr/local/go-faketime/src/runtime/proc.go 250 } } func B() error { return errors.New("error!") } // https://go.dev/play/p/DkGku2xlhSr