问题描述
代码:
package main
import (
"fmt"
"runtime"
)
func foo() {
bar()
}
func bar() {
pcs := make([]uintptr,10)
_ = runtime.Callers(0,pcs)
for _,pc := range pcs {
fmt.Printf("Value of pc %+v\n",runtime.FuncForPC(pc).Name())
}
}
func main() {
foo()
}
- 使用
go run
或已编译的二进制文件运行时,它会打印(缺少main.bar
)
Value of pc runtime.Callers
Value of pc runtime.Callers
Value of pc main.main
Value of pc main.foo
Value of pc runtime.main
Value of pc runtime.goexit
Value of pc runtime.Callers
Value of pc main.bar
Value of pc main.foo
Value of pc main.main
Value of pc runtime.main
Value of pc runtime.goexit
- 在Playground,(
foo
,bar
中运行时,两者均缺失)
Value of pc runtime.Callers
Value of pc runtime.Callers
Value of pc main.main
Value of pc main.main
Value of pc runtime.main
Value of pc runtime.goexit
我正在使用一个框架(日志),该框架依赖于PC的命令来执行某些操作(记录文件名)。
由于PC值根据其运行位置而不断变化,因此它可以在调试模式下运行,但在使用go run
或编译后的二进制文件运行时会失败。
任何想法都可能导致PC负载不同吗?有任何配置或优化吗?
解决方法
runtime.Callers()
状态的文档:
要将这些PC转换为符号信息,例如函数名称和行号,请使用CallersFrames。 CallersFrames考虑内联函数,并将返回程序计数器调整为调用程序计数器。不建议直接在返回的PC片上进行迭代,就像在任何返回的PC上使用FuncForPC一样,因为它们不能解决内联或返回程序计数器的调整问题。
Doc建议使用runtime.CallersFrames()
从原始计数器获取函数信息,该计数器了解并说明函数内联,例如:
pcs := make([]uintptr,10)
n := runtime.Callers(0,pcs)
pcs = pcs[:n]
frames := runtime.CallersFrames(pcs)
for {
frame,more := frames.Next()
if !more {
break
}
fmt.Println("Function:",frame.Function)
}
无论您如何调用/运行它,都应该输出(在Go Playground上尝试):
Function: runtime.Callers
Function: main.bar
Function: main.foo
Function: main.main
Function: runtime.main