go - runtime.Callers 根据运行的位置打印不同的程序计数器

标签 go runtime logrus

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

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
    
  • 从 Visual Studio Code 运行代码时(仅在 调试 模式下,它工作正常)
  • 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
    
    我正在使用一个框架(logrus),它依赖于 PC 的顺序来执行一些操作(记录文件名)。由于 PC 值会根据其运行位置不断变化,因此它可以在 Debug模式下工作,但在使用 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.


    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
    

    关于go - runtime.Callers 根据运行的位置打印不同的程序计数器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64135896/

    相关文章:

    json - 无法将 []interface{} 转换为 []byte : "interface {} is []interface [], not []uint8"

    json - 如何创建这个 JSON 对象?

    rest - REST api设计的GET方法中的HTTP状态码

    go - 如何从http响应中提取某个 header [Set-Cookie]

    c# - 当新版本已签名但以前未签名时,.NET 程序集绑定(bind)重定向

    java - 开发 Eclipse 插件期间的运行时问题

    runtime - 运行 PowerBuilder 应用程序

    go - 如何在 macOS 上的 logrus/lumberjack 中自动重新创建日志文件

    go - 处理程序服务后,如何从请求对象取回记录器对象?