2012-05-24 2743 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

在我看来,main的类型是'function'。你会期望什么作为一个名字? –

+0

这是一个非常重要的点。代码示例应该可能不起作用,但我认为问题的名称是有效的。 – Laserallan

回答

20

的解决方案是使用FuncForPc返回一个*Func

这将返回"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.main
的功能名称:main.x
的功能名称:主。 y
功能名称:main.z

+0

个人而言,我更喜欢你的解决方案(或@ Koala3的扩展在你自己的解决方案),主要是因为它允许将运行时调用封装在一个函数中,然后可以“安全”地部署到其他地方;如果Go运行时由于某种原因改变了功能,那么整个代码需要在一个地方改变。此外,避免反射是一个巧妙的技巧,做得好! :) –

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

使用函数名保持包名的好处当然是,有可能在不同的包中有多个具有相同名称的函数......然后你不知道哪个是哪个:)事实上,我在SO上搜索这个答案的主要原因是因为我不确定哪些函数导致了错误,并且我需要追踪除函数名称之外的精确包名... 请注意,您需要导入'字符串'和'文件路径'以及您的解决方案的工作! –