2012-05-24 12 views
11

Estoy tratando de usar el sistema de reflexión de Go para recuperar el nombre de una función pero obtengo una cadena vacía cuando llamo al método Name en su tipo. ¿Es este el comportamiento esperado?Obtener el nombre de la función usando la reflexión en Golang

Este es un ejemplo sencillo de cómo abordar el problema:

package main 

import "fmt" 
import "reflect" 

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

Me parece que el tipo de main es 'function'. ¿Qué esperarías como nombre? –

+0

Eso es un punto. El ejemplo de código probablemente no funcione, pero creo que el nombre de la pregunta es válido. – Laserallan

Respuesta

20

La solución es utilizar FuncForPc que devuelve un *Func.

Esto devuelve "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) 
} 

Si desea "main", simplemente tokenize ella.

+0

Gracias. ¡Esto resolvió el problema! – Laserallan

+9

O, sin reflejar, pc, _, _, _: = runtime.Caller (0) fmt.Println ("Nombre de la función:" + runtime.FuncForPC (pc) .Name()) – Sonia

+0

Interesante. Pero suponía que OP estaba buscando una solución más general, con cualquier función. –

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

Salida:

Nombre de la función: main.main

Nombre de la función: main.main
Nombre de la función: main.x
Nombre de la función: principal. y
Nombre de la función: main.z

+0

Personalmente, prefiero su solución (o la extensión de @ Koala3 en su propia solución), sobre todo porque permite encapsular las llamadas en tiempo de ejecución dentro de una función que luego puede desplegarse 'de manera segura' en otro lugar; si el tiempo de ejecución de Go funciona por algún motivo, entonces todo el código debe cambiarse en un solo punto. Además, evitar la reflexión es un buen truco, ¡bien hecho! :) –

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

La ventaja de mantener el nombre del paquete con el nombre de la función es, por supuesto, que es posible tener varias funciones con el mismo nombre en diferentes paquetes ... y luego no tienes idea de cuál es cuál :) De hecho, El motivo principal por el que busqué esta respuesta en SO fue porque no estaba seguro de cuál de mis funciones estaba causando un error, y necesitaba buscar el nombre exacto del paquete además del nombre de la función ... Tenga en cuenta que necesita ¡importe 'cadenas' y' filepath' para que su solución funcione! –

Cuestiones relacionadas