【问题标题】:How to get the current function name如何获取当前函数名
【发布时间】:2021-02-26 01:17:23
【问题描述】:

出于跟踪目的,我想打印出当前函数名称,例如 gcc 中的 __FUNCTION__ 宏。

这样当我有一个功能时

func foo () {
   trace()
}

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

【问题讨论】:

标签: go


【解决方案1】:

[注意:Go 1.7+ 建议使用runtime.CallersFrames 而不是runtime.FuncForPCanother answer 有一个更新的例子]。

包裹runtime是你的朋友:

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

【讨论】:

  • 仅供参考 - 文档确实说明了这一点,但这似乎不准确。我调用了这 3 个方法,它在第 22 行时报告源文件中的第 24 行。然后我尝试了一个方法调用 deep 并且它是一行 - 不足以满足我的要求:(文档确实说明The result will not be accurate if pc is not a program counter within f ..但我不确定我应该如何解释。似乎不如从堆栈跟踪中提取文件和行号准确。
  • 从google偶然发现了这个,但是上面的函数报告了下一个执行的函数的行号,在这里试试play.golang.org/p/hpOXSUb8sD。然而,这实际上是正确的行为,并记录在此处godoc.org/runtime#Callers
  • 调用者函数的 Golang 文档在 1.9 中更改为 github repo 1.6 文档的永久链接:github.com/golang/go/blob/release-branch.go1.6/src/runtime/…
【解决方案2】:

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

来自Go 1.7 Release Notes

新函数 CallersFrames 将从 Callers 获得的 PC 切片转换为与调用堆栈对应的帧序列。应该首选这个新 API 而不是直接使用 FuncForPC,因为帧序列可以更准确地描述内联函数调用的调用堆栈。

一个改进的例子:

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

游乐场:https://play.golang.org/p/YkEN5mmbRld

【讨论】:

    【解决方案3】:

    这是一个更简单的版本,不需要分配数组。

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

    【讨论】:

    猜你喜欢
    • 2020-02-28
    • 2014-01-15
    • 2012-04-25
    • 1970-01-01
    • 1970-01-01
    • 2011-04-17
    • 2011-06-11
    • 2011-09-29
    • 1970-01-01
    相关资源
    最近更新 更多