【发布时间】:2021-02-26 01:17:23
【问题描述】:
出于跟踪目的,我想打印出当前函数名称,例如 gcc 中的 __FUNCTION__ 宏。
这样当我有一个功能时
func foo () {
trace()
}
它会自动打印出Entering foo()... 或类似的东西。
【问题讨论】:
标签: go
出于跟踪目的,我想打印出当前函数名称,例如 gcc 中的 __FUNCTION__ 宏。
这样当我有一个功能时
func foo () {
trace()
}
它会自动打印出Entering foo()... 或类似的东西。
【问题讨论】:
标签: go
[注意:Go 1.7+ 建议使用runtime.CallersFrames 而不是runtime.FuncForPC; another 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())
}
【讨论】:
The result will not be accurate if pc is not a program counter within f ..但我不确定我应该如何解释。似乎不如从堆栈跟踪中提取文件和行号准确。
Go 1.7 添加了一些运行时函数来改进对堆栈帧信息的访问。
新函数 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)
}
【讨论】:
这是一个更简单的版本,不需要分配数组。
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()
}
【讨论】: