技術向上

プログラミングの学び、気になるテクノロジーやビジネストレンドを発信

実行時の関数名やファイルパス、行数を取得する【Go】

runtimeパッケージのCallerを用いて取得することができます。

package main

import (
    "runtime"
    "fmt"
)

func main() {
    pc, pwd, line, ok := runtime.Caller(0)
    fn := runtime.FuncForPC(pc)
    fmt.Println(pc, pwd, line, ok, fn.Name())
}


runtime.Caller()の引数はint型のskipと定義され、gorutineのスタック上に実行順で積み上げられた関数から、どれを取得するかを指定します。

0がCaller()呼び出し元の関数です。上記例では、ついでmainパッケージのmain関数、ついでruntimeパッケージのmain関数、runtimeパッケージのgoexit関数です。

例えば下記のように、複数の関数を実行させた場合、

package main

import (
    "runtime"
    "fmt"
)

func main() {
    test()
}

func test() {
    pc, pwd, line, ok := runtime.Caller(0)
    fn := runtime.FuncForPC(pc)
    fmt.Println(pc, pwd, line, ok, fn.Name())
}


0がmain.test、1がmain.main、2がruntime.main、3がruntime.goexitとなります。

runtime.goexitはgorutineを終了させる関数です。

runtime.Caller()の第1返り値は、pc、プログラムカウンターで、次に実行する命令を保存したメモリ上のアドレスを保存したものです。
runtime.FuncForPC()の引数に与えて実行することで、関数の情報を取得することができ、Name()を使って、関数名を取得しています。

第2返り値はpwdで、その関数が記述されたファイルの現在地(ファイルパス)です。

第3返り値は Caller()が記述されている行を示します。

Caller()が内容を取得できなかった場合、第4返り値がfalseになります。


これらはアプリケーションのログ出力に役立ちます。