Go言語(golang) 実行ファイルのファイル名や行番号、関数名などを取得する
runtime.Callerやruntime.FuncForPCを使って
実行ファイルのパスや実行している行番号、関数名などを取得する
目次
行番号やファイル名の取得(runtime.Caller)
func Caller(skip int) (pc uintptr, file string, line int, ok bool)
引数
- skip: フレームをどこまで遡るか
戻り値
- pc : メモリのアドレス
- file: ファイル名
- line: 関数が呼ばれた行番号。
- ok : 取得できたかどうかの真偽値
package main import "runtime" func main() { pc, file, line, ok := runtime.Caller(0) if ok { println(pc, file, line) } _, name, _, _ := runtime.Caller(0) println(name) // /go/src/main.go _, name, _, _ = runtime.Caller(1) println(name) // /src/runtime/proc.go }
引数skipについて
Bは関数一つ分ズレる
package main import "runtime" func A(skip int) { _, name, _, _ := runtime.Caller(skip) println(name) } func B(skip int) { A(skip) } func main() { A(0) // /path/to/dir/main.go A(1) // /path/to/dir/main.go A(2) // /src/runtime/proc.go A(3) // /src/runtime/asm_amd64.s A(4) // 空 B(0) // /path/to/dir/main.go B(1) // /path/to/dir/main.go B(2) // /path/to/dir/main.go B(3) // /src/runtime/proc.go B(4) // /src/runtime/asm_amd64.s }
関数名の取得(runtime.FuncForPC)
package main import ( "reflect" "runtime" ) func function() {} func main() { rv := reflect.ValueOf(function) name := runtime.FuncForPC(rv.Pointer()).Name() println(name) // main.function rv = reflect.ValueOf(runtime.FuncForPC) name = runtime.FuncForPC(rv.Pointer()).Name() println(name) // runtime.FuncForPC }
関数が定義されている行番号の取得(FileLine)
package main import ( "fmt" "reflect" "runtime" ) func function() {} func main() { rv := reflect.ValueOf(function) ffpc := runtime.FuncForPC(rv.Pointer()) println(rv.Pointer() == ffpc.Entry()) // true FuncForPC に渡したポインタと同じ file, line := ffpc.FileLine(ffpc.Entry()) fmt.Println(file, line) // /path/to/dir/main.go 9 println(ffpc.Name()) // main.function }