以下の内容はhttps://devlights.hatenablog.com/entry/2025/03/17/073000より取得しました。


Goメモ-553 (GOTRACEBACKの設定値をプログラムで設定)(runtime/debug.SetTraceback)

関連記事

GitHub - devlights/blog-summary: ブログ「いろいろ備忘録日記」のまとめ

概要

以下、自分用のメモです。

パニック時の出力の詳細度を設定する環境変数に GOTRACEBACK があります。

runtimeパッケージ のところに記載があり、設定出来る値について書かれています。

Go 1.24の時点で以下の設定値がありますね。

  • none
  • single
  • all
  • system
  • crach
  • wer

single がデフォルト値です。

環境変数なので通常は

$ GOTRACEBACK=all ./app

のように指定して実行するのですが、プログラムからも debug.SetTraceback() で設定出来ます。

試してみた

main.go

2秒したらパニックするプログラムを用意。

/*
GOTRACEBACKの値をプログラムから設定するサンプル

GOTRACEBACKは、Goのプログラムがパニックを起こした際の出力の詳細度を制御する環境変数。
プログラムからも設定することが可能で ```runtime/debug.SetTraceback()``` で設定できる。

   debug.SetTraceback("all")

指定出来る値として

  - none
  - single (デフォルト)
  - all
  - system
  - crach
  - wer

がある。

# REFERENCES
  - https://pkg.go.dev/runtime/debug#SetTraceback
  - https://pkg.go.dev/runtime#hdr-Environment_Variables
  - https://go.dev/doc/godebug
*/
package main

import (
    "flag"
    "fmt"
    "runtime/debug"
    "sync"
    "time"
)

type (
    Args struct {
        Traceback string
    }
)

var (
    args Args
)

func init() {
    flag.StringVar(&args.Traceback, "traceback", "single", "GOTRACEBACK (none, single, all, system, crach, wer)")
}

func main() {
    flag.Parse()

    if args.Traceback == "" {
        args.Traceback = "single"
    }
    debug.SetTraceback(args.Traceback)

    if err := run(); err != nil {
        panic(err)
    }
}

func run() error {
    //
    // 2秒経過後に意図的にパニックさせる
    //
    ch := make(chan int)
    wg := sync.WaitGroup{}

    wg.Add(3)

    go func(ch chan<- int) {
        defer wg.Done()
        for i := range 100 {
            ch <- i
            time.Sleep(500 * time.Millisecond)
        }
    }(ch)
    go func(ch <-chan int) {
        defer wg.Done()
        for i := range ch {
            fmt.Println(i)
        }
    }(ch)
    go func(ch chan<- int) {
        defer wg.Done()
        defer close(ch)
        time.Sleep(2 * time.Second)
    }(ch)

    wg.Wait()

    return nil
}

Taskfile.yml

# https://taskfile.dev

version: '3'

vars:
  APP_NAME: app

tasks:
  default:
    cmds:
      - task: clean
      - task: run
  install-panicparse:
    cmds:
      - go install github.com/maruel/panicparse/v2/cmd/pp@latest
    status:
      - which pp
  clean:
    cmds:
      - rm -f ./{{.APP_NAME}}{{exeExt}}
    status:
      - test ! -f ./{{.APP_NAME}}{{exeExt}}
  build:
    cmds:
      - go build -o {{.APP_NAME}}{{exeExt}} .
  run:
    deps: [ build, install-panicparse ]
    cmds:
      - for: [ 'none', 'single', 'all', 'system', 'crach', 'wer' ]
        cmd: ./{{.APP_NAME}}{{exeExt}} -traceback {{.ITEM}} |& pp
    ignore_error: true

shell

実行すると以下のように出力されます。設定値ごとに出力される情報の増減がありますね。

$ task
task: [clean] rm -f ./app
task: [build] go build -o app .
task: Task "install-panicparse" is up to date

task: [run] ./app -traceback none |& pp
0
1
2
3
panic: send on closed channel


To see all goroutines, visit https://github.com/maruel/panicparse#gotraceback

1: running [Created by main.run in goroutine 1 @ main.go:71]
    main main.go:74 run.func1(0xc000096070)


task: [run] ./app -traceback single |& pp
0
1
2
3
panic: send on closed channel


To see all goroutines, visit https://github.com/maruel/panicparse#gotraceback

1: running [Created by main.run in goroutine 1 @ main.go:71]
    main main.go:74 run.func1(0xc000096070)


task: [run] ./app -traceback all |& pp
0
1
2
3
panic: send on closed channel

1: running [Created by main.run in goroutine 1 @ main.go:71]
    main main.go:74       run.func1(0xc000096070)
1: runnable
    sync sema.go:110      runtime_SemacquireWaitGroup(*uint32(#1))
    sync waitgroup.go:118 (*WaitGroup).Wait(*WaitGroup(#2))
    main main.go:90       run()
    main main.go:57       main()


task: [run] ./app -traceback system |& pp
0
1
2
3
panic: send on closed channel

goroutine 18 gp=0xc000102540 m=0 mp=0x5746c0 [running]:
panic({0x4ab820?, 0x4e8710?})
        /home/gitpod/go/src/runtime/panic.go:811 +0x168 fp=0xc0000646d8 sp=0xc000064628 pc=0x468728
runtime.chansend(0xc000116070, 0xc000064798, 0x1, 0xc000102540?)
        /home/gitpod/go/src/runtime/chan.go:226 +0x55e fp=0xc000064748 sp=0xc0000646d8 pc=0x40b73e
runtime.chansend1(0x1dcd6500?, 0x0?)
        /home/gitpod/go/src/runtime/chan.go:161 +0x17 fp=0xc000064778 sp=0xc000064748 pc=0x40b1d7
main.run.func1(0xc000116070)
        /workspace/try-golang/examples/singleapp/debug_settraceback/main.go:74 +0x5f fp=0xc0000647c8 sp=0xc000064778 pc=0x49c83f
main.run.gowrap1()
        /workspace/try-golang/examples/singleapp/debug_settraceback/main.go:77 +0x24 fp=0xc0000647e0 sp=0xc0000647c8 pc=0x49c7a4
runtime.goexit({})
        /home/gitpod/go/src/runtime/asm_amd64.s:1700 +0x1 fp=0xc0000647e8 sp=0xc0000647e0 pc=0x46f441
created by main.run in goroutine 1
        /workspace/try-golang/examples/singleapp/debug_settraceback/main.go:71 +0xd1

goroutine 1 gp=0xc000002380 m=nil [runnable]:
runtime.Gosched(...)
        /home/gitpod/go/src/runtime/proc.go:364
runtime.main()
        /home/gitpod/go/src/runtime/proc.go:299 +0x313 fp=0xc000120fe0 sp=0xc000120f50 pc=0x43a353
runtime.goexit({})
        /home/gitpod/go/src/runtime/asm_amd64.s:1700 +0x1 fp=0xc000120fe8 sp=0xc000120fe0 pc=0x46f441

goroutine 2 gp=0xc0000028c0 m=nil [force gc (idle)]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
        /home/gitpod/go/src/runtime/proc.go:435 +0xce fp=0xc000068fa8 sp=0xc000068f88 pc=0x468b4e
runtime.goparkunlock(...)
        /home/gitpod/go/src/runtime/proc.go:441
runtime.forcegchelper()
        /home/gitpod/go/src/runtime/proc.go:348 +0xb3 fp=0xc000068fe0 sp=0xc000068fa8 pc=0x43a613
runtime.goexit({})
        /home/gitpod/go/src/runtime/asm_amd64.s:1700 +0x1 fp=0xc000068fe8 sp=0xc000068fe0 pc=0x46f441
created by runtime.init.7 in goroutine 1
        /home/gitpod/go/src/runtime/proc.go:336 +0x1a

goroutine 3 gp=0xc000002e00 m=nil [GC sweep wait]:
runtime.gopark(0x0?, 0x0?, 0x0?, 0x0?, 0x0?)
        /home/gitpod/go/src/runtime/proc.go:435 +0xce fp=0xc000069780 sp=0xc000069760 pc=0x468b4e
runtime.goparkunlock(...)
        /home/gitpod/go/src/runtime/proc.go:441
runtime.bgsweep(0xc00001e080)
        /home/gitpod/go/src/runtime/mgcsweep.go:276 +0x94 fp=0xc0000697c8 sp=0xc000069780 pc=0x4261b4
runtime.gcenable.gowrap1()
        /home/gitpod/go/src/runtime/mgc.go:204 +0x25 fp=0xc0000697e0 sp=0xc0000697c8 pc=0x41a8e5
runtime.goexit({})
        /home/gitpod/go/src/runtime/asm_amd64.s:1700 +0x1 fp=0xc0000697e8 sp=0xc0000697e0 pc=0x46f441
created by runtime.gcenable in goroutine 1
        /home/gitpod/go/src/runtime/mgc.go:204 +0x66

goroutine 4 gp=0xc000002fc0 m=nil [GC scavenge wait]:
runtime.gopark(0xc00001e080?, 0x4e7c80?, 0x1?, 0x0?, 0xc000002fc0?)
        /home/gitpod/go/src/runtime/proc.go:435 +0xce fp=0xc000069f78 sp=0xc000069f58 pc=0x468b4e
runtime.goparkunlock(...)
        /home/gitpod/go/src/runtime/proc.go:441
runtime.(*scavengerState).park(0x5738e0)
        /home/gitpod/go/src/runtime/mgcscavenge.go:425 +0x49 fp=0xc000069fa8 sp=0xc000069f78 pc=0x423c69
runtime.bgscavenge(0xc00001e080)
        /home/gitpod/go/src/runtime/mgcscavenge.go:653 +0x3c fp=0xc000069fc8 sp=0xc000069fa8 pc=0x4241dc
runtime.gcenable.gowrap2()
        /home/gitpod/go/src/runtime/mgc.go:205 +0x25 fp=0xc000069fe0 sp=0xc000069fc8 pc=0x41a885
runtime.goexit({})
        /home/gitpod/go/src/runtime/asm_amd64.s:1700 +0x1 fp=0xc000069fe8 sp=0xc000069fe0 pc=0x46f441
created by runtime.gcenable in goroutine 1
        /home/gitpod/go/src/runtime/mgc.go:205 +0xa5

goroutine 17 gp=0xc000102380 m=nil [finalizer wait]:
runtime.gopark(0x593ea0?, 0x490013?, 0x78?, 0x86?, 0x412b1e?)
        /home/gitpod/go/src/runtime/proc.go:435 +0xce fp=0xc000068630 sp=0xc000068610 pc=0x468b4e
runtime.runfinq()
        /home/gitpod/go/src/runtime/mfinal.go:196 +0x107 fp=0xc0000687e0 sp=0xc000068630 pc=0x4198a7
runtime.goexit({})
        /home/gitpod/go/src/runtime/asm_amd64.s:1700 +0x1 fp=0xc0000687e8 sp=0xc0000687e0 pc=0x46f441
created by runtime.createfing in goroutine 1
        /home/gitpod/go/src/runtime/mfinal.go:166 +0x3d


task: [run] ./app -traceback crach |& pp
0
1
2
3
panic: send on closed channel

1: running [Created by main.run in goroutine 1 @ main.go:71]
    main main.go:74       run.func1(0xc000116070)
1: runnable
    sync sema.go:110      runtime_SemacquireWaitGroup(*uint32(#2))
    sync waitgroup.go:118 (*WaitGroup).Wait(*WaitGroup(#1))
    main main.go:90       run()
    main main.go:57       main()


task: [run] ./app -traceback wer |& pp
0
1
2
3
panic: send on closed channel

1: running [Created by main.run in goroutine 1 @ main.go:71]
    main main.go:74       run.func1(0xc000096070)
1: runnable
    sync sema.go:110      runtime_SemacquireWaitGroup(*uint32(#1))
    sync waitgroup.go:118 (*WaitGroup).Wait(*WaitGroup(#2))
    main main.go:90       run()
    main main.go:57       main()

参考情報

github.com

Goのおすすめ書籍


過去の記事については、以下のページからご参照下さい。

サンプルコードは、以下の場所で公開しています。




以上の内容はhttps://devlights.hatenablog.com/entry/2025/03/17/073000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14