概要
以下、自分用のメモです。
runtime.Caller()
と runtime.Callers()
で skip に 0 を渡したときの結果が少しだけ異なるので、忘れないうちにメモメモ。
runtime.Caller() の方は、0 を指定すると左記の関数を呼び出した箇所からスタックトレースが取得できるのに対して
runtime.Callers() の方は、0 を指定すると runtime.Callers() 自身の呼び出しからスタックトレースが取得できる。
サンプル
runtime.Caller
package runtimes import ( "runtime" "strings" "github.com/devlights/gomy/output" ) // Caller は、 runtime.Caller() のサンプルです. // // runtime.Caller() は、呼び出し元のgoroutineのスタックにある関数呼び出しに関するファイルおよび行番号情報を報告してくれる. // // # REFERENCES // - https://pkg.go.dev/runtime@go1.19.3#Caller func Caller() error { var ( programCounter uintptr file string line int ok bool sentinel = "try-golang" ) for skip := 0; ; skip++ { // skip = 0 は、runtime.Caller() の場合は、この関数を呼び出した部分になる. // runtime.Callers() の場合は、runtime.Callers() 自体を表す. // 0 の意味が少し違うことに注意. programCounter, file, line, ok = runtime.Caller(skip) if !ok { break } if !strings.Contains(file, sentinel) { break } output.Stdoutf("[runtime.Caller]", "%v\t%v\t%v\n", programCounter, file, line) } return nil }
実行すると以下ようになります。
gitpod /workspace/try-golang (master) $ task task: [run] go run . -onetime ENTER EXAMPLE NAME: runtime_caller [Name] "runtime_caller" [runtime.Caller] 7941654 /workspace/try-golang/examples/basic/runtimes/caller.go 29 [runtime.Caller] 8978018 /workspace/try-golang/runner/exec.go 52 [runtime.Caller] 8980078 /workspace/try-golang/runner/loop.go 126 [runtime.Caller] 8979303 /workspace/try-golang/runner/loop.go 86 [runtime.Caller] 8982849 /workspace/try-golang/cmd/root.go 66 [runtime.Caller] 8983446 /workspace/try-golang/main.go 6 [Elapsed] 183.92µs
runtime.Callers
package runtimes import ( "runtime" "github.com/devlights/gomy/output" ) // Callers は、 runtime.Callers() のサンプルです。 // // # REFERENCES // - https://pkg.go.dev/runtime@go1.19.3#Callers func Callers() error { var ( skip = 0 pc = make([]uintptr, 10) frameCount = runtime.Callers(skip, pc) frames = runtime.CallersFrames(pc[:frameCount]) ) output.Stdoutf("[runtime.CallersFrames]", "frames=%v\n", frameCount) // *runtime.Frames を イテレーション して値を取得 for { frame, more := frames.Next() output.Stdoutf("[runtime.Frames]", "%v\t%v\t%v\n", frame.PC, frame.File, frame.Line) if !more { break } } return nil }
実行すると以下のようになります。
gitpod /workspace/try-golang (master) $ task task: [run] go run . -onetime ENTER EXAMPLE NAME: runtime_callers [Name] "runtime_callers" [runtime.CallersFrames] frames=9 [runtime.Frames] 7941844 /home/gitpod/go/src/runtime/extern.go 247 [runtime.Frames] 7941826 /workspace/try-golang/examples/basic/runtimes/callers.go 17 [runtime.Frames] 8978018 /workspace/try-golang/runner/exec.go 52 [runtime.Frames] 8980078 /workspace/try-golang/runner/loop.go 126 [runtime.Frames] 8979044 /workspace/try-golang/runner/loop.go 79 [runtime.Frames] 8982849 /workspace/try-golang/cmd/root.go 66 [runtime.Frames] 8983446 /workspace/try-golang/main.go 6 [runtime.Frames] 4438865 /home/gitpod/go/src/runtime/proc.go 250 [runtime.Frames] 4633696 /home/gitpod/go/src/runtime/asm_amd64.s 1594 [Elapsed] 164.88µs
確かに runtime.Callers の結果には一番最初に 7941844 /home/gitpod/go/src/runtime/extern.go 247
が出てきてますね。
参考情報
過去の記事については、以下のページからご参照下さい。
サンプルコードは、以下の場所で公開しています。