runtime.Callers 根据其 运行 的来源打印不同的程序计数器

runtime.Callers print different program counters depending on where its run from

我有下面的代码,它根据 运行 的来源打印不同的程序计数器值。

代码:

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()
}
  1. 当 运行ning 使用 go run 或编译的二进制文件时,它会打印 (main.bar is missing)
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
  1. 当运行从Visual Studio代码中调用代码时(仅在调试模式下,它工作正常)
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
  1. 当运行ning在Playground时,(foobar,两者都不见了)
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

我正在使用一个框架 (logrus),它依赖于 PC 的顺序来执行一些操作(记录文件名)。
由于 PC 值根据其 运行 的来源不断变化,它在调试模式下工作,但在 运行 使用 go run 或编译的二进制文件时失败。

知道是什么导致 PC 加载不同吗?任何配置或优化正在启动?

runtime.Callers() 的文档说明:

To translate these PCs into symbolic information such as function names and line numbers, use CallersFrames. CallersFrames accounts for inlined functions and adjusts the return program counters into call program counters. Iterating over the returned slice of PCs directly is discouraged, as is using FuncForPC on any of the returned PCs, since these cannot account for inlining or return program counter adjustment.

文档建议使用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