2012-05-24 10 views
11

Goの反射システムを使用して関数の名前を取得しようとしていますが、その型のNameメソッドを呼び出すときに空の文字列が返されます。これは期待される行動ですか?Golangのリフレクションを使用して関数の名前を取得する

これは、私が問題にアプローチする方法の簡単な例は次のとおりです。

package main 

import "fmt" 
import "reflect" 

func main() { 
    typ := reflect.TypeOf(main) 
    name := typ.Name() 
    fmt.Println("Name of function" + name) 
} 
+1

メインのタイプは 'function'です。あなたは名前として何を期待しますか? –

+0

それは非常に重要です。コード例はおそらく動作しませんが、私は質問の名前が有効だと思います。 – Laserallan

答えて

20

ソリューションは*Func返しFuncForPcを使用することです。

これは"main.main"を返します。

package main 

import "fmt" 
import "reflect" 
import "runtime" 


func main() { 
    name := runtime.FuncForPC(reflect.ValueOf(main).Pointer()).Name() 
    fmt.Println("Name of function : " + name) 
} 

あなたが"main"をしたい場合は、ちょうどそれをトークン化。

+0

ありがとうございます。これは問題を解決しました! – Laserallan

+9

または、反映しないで、pc、_、_、_:= runtime.Caller(0) fmt.Println( "関数名:" + runtime.FuncForPC(pc).Name()) – Sonia

+0

興味深い。しかし、私はOPがどんな機能であれ、より一般的な解決策を探していると仮定していました。 –

25
package main 

import "fmt" 
import "runtime" 

func main() { 
    pc, _, _, _ := runtime.Caller(0) 
    fmt.Println("Name of function: " + runtime.FuncForPC(pc).Name()) 
    fmt.Println() 

    // or, define a function for it 
    fmt.Println("Name of function: " + funcName()) 
    x() 
} 

func funcName() string { 
    pc, _, _, _ := runtime.Caller(1) 
    return runtime.FuncForPC(pc).Name() 
} 

func x() { 
    fmt.Println("Name of function: " + funcName()) 
    y() 
} 

func y() { 
    fmt.Println("Name of function: " + funcName()) 
    z() 
} 
func z() { 
    fmt.Println("Name of function: " + funcName()) 
} 

出力:機能の

名:機能のmain.main

名:機能のmain.x
名:主な機能の
名前をmain.main。 y
機能の名称:main.z

+0

個人的には、自分のソリューション(または@ Koala3の拡張は自分のソリューションで)が好きです。なぜなら、実行時呼び出しを関数内にカプセル化して他の場所に「安全に」配置できるからです。何らかの理由でGoランタイム関数が変更された場合、コード全体を1箇所で変更する必要があります。また、リフレクションを避けることはすっきりしたトリックです。 :) –

2
import runtime 

func funcName() string { 
    pc, _, _, _ := runtime.Caller(1) 
    nameFull := runtime.FuncForPC(pc).Name() // main.foo 
    nameEnd := filepath.Ext(nameFull)   // .foo 
    name := strings.TrimPrefix(nameEnd, ".") // foo 
    return name 
} 
+0

パッケージ名を関数名に保つことの利点は、もちろん、異なるパッケージに同じ名前の関数を複数持つことが可能であるということです。そして、どちらがどのようなものか分かりません:)実際、この回答を検索する主な理由は、関数のどれがエラーを引き起こしているのか不明で、関数名のほかに正確なパッケージ名を追跡する必要があったためです。 あなたの解決策がうまくいくために 'strings'と' filepath'をインポートしてください! –

関連する問題