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

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

syumai
March 26, 2023

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

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