2012-05-24 9 views
11

Ich versuche Go-Reflexionssystem zu verwenden, um den Namen einer Funktion abzurufen, aber ich erhalte eine leere Zeichenfolge beim Aufrufen der Methode Name auf seinem Typ. Ist das das erwartete Verhalten?Get Name der Funktion mit Reflektion in Golang

Dies ist ein einfaches Beispiel dafür, wie ich Ansatz das Problem:

package main 

import "fmt" 
import "reflect" 

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

Es scheint mir, dass der Typ von main "Funktion" ist. Was würdest du als Namen erwarten? –

+0

Das ist ein sehr wichtiger Punkt. Das Codebeispiel sollte wahrscheinlich nicht funktionieren, aber ich denke, der Name der Frage ist gültig. – Laserallan

Antwort

20

Die Lösung ist FuncForPc zu verwenden, die eine *Func zurückgibt.

Das gibt "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) 
} 

Wenn Sie "main" wollen, ist es nur tokenize.

+0

Danke. Das hat das Problem gelöst! – Laserallan

+9

Oder, ohne zu reflektieren, pc, _, _, _: = Laufzeit.Caller (0) fmt.Println ("Name der Funktion:" + runtime.FuncForPC (pc) .Name()) – Sonia

+0

Interessant. Aber ich nahm an, OP suchte nach einer allgemeineren Lösung mit jeder Funktion. –

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()) 
} 

Output:

Funktionsname: main.main

Name der Funktion: main.main
Name der Funktion: main.x
Name der Funktion: main. y
Name der Funktion: main.z

+0

Persönlich bevorzuge ich Ihre Lösung (oder @ Koala3 Erweiterung auf Ihre eigene Lösung), vor allem, weil es ermöglicht, die Laufzeitaufrufe innerhalb einer Funktion zu kapseln, die dann "sicher" anderswo eingesetzt werden kann; Wenn sich die Go-Laufzeit aus irgendeinem Grund ändert, muss der gesamte Code nur an einer Stelle geändert werden. Reflektieren ist auch ein netter Trick, gut gemacht! :) –

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

Der Vorteil des Speicherns des Paketnamens mit dem Funktionsnamen ist natürlich, dass es möglich ist, mehrere Funktionen mit demselben Namen in verschiedenen Paketen zu haben ... und dann hast du keine Ahnung, welches was ist :) Tatsächlich der Hauptgrund für mich, nach dieser Antwort auf SO zu suchen, war, weil ich nicht sicher war, welche meiner Funktionen einen Fehler verursachte, und ich den genauen Paketnamen neben dem Funktionsnamen aufspüren musste ... Beachten Sie, dass Sie müssen Importieren Sie 'strings' und' filepath', damit Ihre Lösung funktioniert! –