2012-05-24 7 views
11

Sto cercando di utilizzare il sistema di riflessione di Go per recuperare il nome di una funzione, ma ottengo una stringa vuota quando si chiama il metodo Name sul suo tipo. È questo il comportamento previsto?Ottieni il nome della funzione utilizzando la riflessione in Golang

Questo è un semplice esempio di come mi avvicino il problema:

package main 

import "fmt" 
import "reflect" 

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

Mi sembra che il tipo di main sia 'function'. Cosa ti aspetteresti come nome? –

+0

Questo è un punto molto. L'esempio di codice probabilmente non dovrebbe funzionare, ma penso che il nome della domanda sia valido. – Laserallan

risposta

20

La soluzione è quella di utilizzare FuncForPc che restituisce un *Func.

Ciò restituisce "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) 
} 

Se si desidera "main", basta tokenize esso.

+0

Grazie. Questo ha risolto il problema! – Laserallan

+9

Oppure, senza riflettere, pc, _, _, _: = runtime.Caller (0) fmt.Println ("Nome della funzione:" + runtime.FuncForPC (pc) .Name()) – Sonia

+0

Interessante. Ma supponevo che OP cercasse una soluzione più generale, con qualsiasi funzione. –

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

uscita:

Nome della funzione: main.main

Nome della funzione: main.main
Nome della funzione: main.x
Nome della funzione: principale. y
Nome della funzione: main.z

+0

Personalmente, preferisco la soluzione (o l'estensione @ Koala3 sulla propria soluzione), principalmente perché consente di incapsulare le chiamate di runtime all'interno di una funzione che può quindi essere distribuita "in sicurezza" altrove; se il runtime di Go funziona per qualche motivo, allora l'intero codice deve essere cambiato in un solo punto. Inoltre, evitare la riflessione è un trucco pulito, ben fatto! :) –

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

Il vantaggio di mantenere il nome del pacchetto con il nome della funzione è, ovviamente, che è possibile avere diverse funzioni con lo stesso nome in pacchetti diversi ... e quindi non si ha idea di quale sia :) In effetti, il motivo principale per cui ho cercato questa risposta su SO era perché non ero sicuro di quale delle mie funzioni stesse causando un errore, e avevo bisogno di rintracciare il nome preciso del pacchetto oltre al nome della funzione ... Nota che è necessario importate 'stringhe' e' filepath's per far funzionare la vostra soluzione! –