如何在Go中获取函数名称?


101

给定一个函数,可以得到它的名字吗?说:

func foo() {
}

func GetFunctionName(i interface{}) string {
    // ...
}

func main() {
    // Will print "name: foo"
    fmt.Println("name:", GetFunctionName(foo))
}

有人告诉我runtime.FuncForPC会有所帮助,但我不明白如何使用它。

Answers:


187

很抱歉回答我自己的问题,但我找到了解决方案:

package main

import (
    "fmt"
    "reflect"
    "runtime"
)

func foo() {
}

func GetFunctionName(i interface{}) string {
    return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
}

func main() {
    // This will print "name: main.foo"
    fmt.Println("name:", GetFunctionName(foo))
}

2
尽管这似乎可行,但是在这里可能需要格外小心:.Pointer()的文档指出“如果v的Kind为Func,则返回的指针是基础代码指针,但不一定足以唯一地标识单个函数。唯一的确保且仅当v为nil func值时,结果为零。”
jochen 2015年

1
@jochen“不是单个函数”是否意味着它可能返回假阳性(即,不同函数的指针)?
themihai

1
@themihai我不知道,我引用这句话是所有在文档golang.org/pkg/reflect/#Value.Pointer说这件事。但是引号似乎表明一个人可以为不同的函数获得相同的指针,不是吗?如果是这种情况,GetFunctionName是否可能为不同的函数返回相同的名称?
jochen 2016年

3
@jochen我认为这与闭包有关;如果创建两个具有相同基础功能的闭包,则即使闭包的值不同,它们也将是等效的。
Alex Guerra

9

由于它记录了文件名和行号,因此不完全是您想要的,但这是我使用“运行时”程序包在Tideland Common Go库(http://tideland-cgl.googlecode.com/)中进行的操作:

// Debug prints a debug information to the log with file and line.
func Debug(format string, a ...interface{}) {
    _, file, line, _ := runtime.Caller(1)
    info := fmt.Sprintf(format, a...)

    log.Printf("[cgl] debug %s:%d %v", file, line, info)

1
那真的没有帮助。我不需要获取有关调用堆栈的信息,而只需获取给定功能的信息。我相信如果我知道如何在给定功能引用的情况下获取相应的pc(如果可能的话),就会回答该问题。
moraes
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.