如何获取当前函数名

huangapple go评论146阅读模式
英文:

How to get the current function name

问题

为了追踪目的,我想要打印出当前函数的名称,就像gcc中的__FUNCTION__宏一样。

这样当我有一个函数:

func foo() {
   trace()
}

它会自动打印出Entering foo()...或类似的内容。

英文:

For tracing purpose, I'd like to print out current function name, like the __FUNCTION__ macro in gcc.

So that when I have a function

func foo () {
   trace()
}

it will automatically print out Entering foo()... or something like that.

答案1

得分: 71

[注意:Go 1.7+建议使用runtime.CallersFrames而不是runtime.FuncForPC另一个答案有一个更新的示例。]

在这里,runtime包是你的朋友:

func trace() {
    pc := make([]uintptr, 10)  // 至少需要1个条目
    runtime.Callers(2, pc)
    f := runtime.FuncForPC(pc[0])
    file, line := f.FileLine(pc[0])
    fmt.Printf("%s:%d %s\n", file, line, f.Name())
}
英文:

[Note: Go 1.7+ recommends using runtime.CallersFrames instead of runtime.FuncForPC; another answer has an updated example].

Package runtime is your friend here:

func trace() {
    pc := make([]uintptr, 10)  // at least 1 entry needed
    runtime.Callers(2, pc)
    f := runtime.FuncForPC(pc[0])
    file, line := f.FileLine(pc[0])
    fmt.Printf("%s:%d %s\n", file, line, f.Name())
}

答案2

得分: 52

Go 1.7增加了一些运行时函数来改进访问堆栈帧信息。

Go 1.7发布说明中可以看到:

新的函数CallersFrames将从Callers获取的PC切片转换为与调用堆栈对应的帧序列。与直接使用FuncForPC相比,应优先使用这个新的API,因为帧序列可以更准确地描述内联函数调用的调用堆栈。

改进后的示例代码:

func trace2() {
    pc := make([]uintptr, 15)
    n := runtime.Callers(2, pc)
    frames := runtime.CallersFrames(pc[:n])
    frame, _ := frames.Next()
    fmt.Printf("%s:%d %s\n", frame.File, frame.Line, frame.Function)
}

Playground: https://play.golang.org/p/YkEN5mmbRld

英文:

Go 1.7 added some runtime functions to improve accessing stack frame information.

From the Go 1.7 Release Notes:

> The new function CallersFrames translates a PC slice obtained from Callers into a sequence of frames corresponding to the call stack. This new API should be preferred instead of direct use of FuncForPC, because the frame sequence can more accurately describe call stacks with inlined function calls.

An improved example:

func trace2() {
    pc := make([]uintptr, 15)
 	n := runtime.Callers(2, pc)
    frames := runtime.CallersFrames(pc[:n])
 	frame, _ := frames.Next()
    fmt.Printf("%s:%d %s\n", frame.File, frame.Line, frame.Function)
}

Playground: https://play.golang.org/p/YkEN5mmbRld

答案3

得分: 10

以下是一个不需要分配数组的简化版本。

func trace() (string, int, string) {
    pc, file, line, ok := runtime.Caller(1)
    if !ok { return "?", 0, "?" }

    fn := runtime.FuncForPC(pc)
    if fn == nil { return file, line, "?" }

    return file, line, fn.Name()
}

这个函数用于获取调用它的函数的文件名、行号和函数名。

英文:

Here's a simpler version that doesn't need to allocate an array.

func trace() (string, int, string) {
    pc, file, line, ok := runtime.Caller(1)
    if !ok { return "?", 0, "?" }

    fn := runtime.FuncForPC(pc)
    if fn == nil { return file, line, "?" }

    return file, line, fn.Name()
}

答案4

得分: 2

pc, _, _, _ := runtime.Caller(0)
log.Println(runtime.FuncForPC(pc).Name())

翻译结果:
pc, _, _, _ := runtime.Caller(0)
log.Println(runtime.FuncForPC(pc).Name())

英文:

pc, _, _, _ := runtime. Caller(0)
log.Println(runtime.FuncForPC(pc).Name())

huangapple
  • 本文由 发表于 2014年9月19日 14:28:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/25927660.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定