0

我有一个简单的 go 代码,它使用运行时包如下:

package main

import (
    "runtime"
    "fmt"
)

func bar() {
    pc := make([]uintptr, 1000)
    n := runtime.Callers(0, pc)
    frames := runtime.CallersFrames(pc[:n])
    for {
        frame, more := frames.Next()
        if ! more {
            break
        }
        fmt.Printf("FILE = %s and FUNC = %s\n", frame.File, frame.Function)
    }
}

func foo() {
    bar()
}

func main() {
    foo()
}

我已经在 Ubuntu 机器(比如机器 A)上的自定义位置(/home/ userA /bin/go)安装了 Go 二进制文件

我已经在机器A上编译它并在同一台机器上运行可执行文件以获得输出:

FILE = /home/userA/bin/go/src/runtime/extern.go and FUNC = runtime.Callers
FILE = /home/userA/src/main.go and FUNC = main.bar
FILE = /home/userA/src/main.go and FUNC = main.foo
FILE = /home/userA/src/main.go and FUNC = main.main
FILE = /home/userA/bin/go/src/runtime/proc.go and FUNC = runtime.main

现在我将编译后的可执行文件复制到另一台 Ubuntu 机器(比如机器 B),其中 Go 二进制文件安装在另一个不同的自定义位置(/home/ userB /bin/go)。我从/home/userB运行可执行文件。但这一次,我得到了和以前一样的输出:

FILE = /home/userA/bin/go/src/runtime/extern.go and FUNC = runtime.Callers
FILE = /home/userA/src/main.go and FUNC = main.bar
FILE = /home/userA/src/main.go and FUNC = main.foo
FILE = /home/userA/src/main.go and FUNC = main.main
FILE = /home/userA/bin/go/src/runtime/proc.go and FUNC = runtime.main

似乎运行时包在编译期间设置了堆栈帧。

我需要根据GOPATH环境变量对文件路径进行一些处理,我在机器 A 上设置为/ home /userA ,在机器B上设置为/home/ userB

我需要从每个文件路径中删除 GOPATH 部分。我用这个简单的函数调用来做到这一点:strings.Replace(frame.File, GOPATH, "", 1)

但是,由于运行时包的这种行为,该strings.Replace函数无法替换机器B上文件路径的初始部分。

关于如何在机器B上完成此操作的任何想法?

更新

按照@JimB 的建议,我用

CGO_ENABLED=0 go build -a -ldflags="-w -s" -gcflags=-trimpath=/home/userA -asmflags=-trimpath=/home/userA

现在,在同一台机器上运行可执行文件会给出如下输出:

FILE = /home/userA/bin/go/src/runtime/extern.go and FUNC = runtime.Callers
FILE = /home/userA/src/vendor/github.com/kataras/golog/golog.go and FUNC = vendor/github.com/kataras/golog.Error
FILE = /home/userA/src/test/test_logger.go and FUNC = test/test_logger.TestLogger
FILE = src/main.go and FUNC = main.bar
FILE = src/main.go and FUNC = main.foo
FILE = src/main.go and FUNC = main.main
FILE = /home/userA/bin/go/src/runtime/proc.go and FUNC = runtime.main

路径前缀仅针对主文件进行修剪。对于任何供应商导入的包或任何本地导入的包,它仍然存在。

4

1 回答 1

0

你想完成什么?XY 问题是询问您尝试的解决方案,而不是您的实际问题:XY 问题


命令去

GOPATH 环境变量列出了查找 Go 代码的位置。在 Unix 上,该值是一个冒号分隔的字符串。在 Windows 上,该值是以分号分隔的字符串。在计划 9 中,值是一个列表。


GOPATH 是 Go 工具的一个工件。Go 语言兼容性保证不涵盖它。

如果 GOPATH 列表包含多个元素,会发生什么?


这对你有用吗?

package main

import (
    "fmt"
    "runtime"
    "strings"
)

func srcFile(path string) string {
    const src = `/src/`
    i := strings.LastIndex(path, src)
    if i >= 0 {
        path = path[i+len(src):]
    }
    return path
}

func bar() {
    pc := make([]uintptr, 1000)
    n := runtime.Callers(0, pc)
    frames := runtime.CallersFrames(pc[:n])
    for {
        frame, more := frames.Next()
        if !more {
            break
        }
        fmt.Printf("PATH = %s and FUNC = %s\n", frame.File, frame.Function)
        fmt.Printf("FILE = %s and FUNC = %s\n", srcFile(frame.File), frame.Function)
    }
}

func foo() {
    bar()
}

func main() {
    foo()
}

输出:

PATH = /home/peter/go/src/runtime/extern.go and FUNC = runtime.Callers
FILE = runtime/extern.go and FUNC = runtime.Callers
PATH = /home/peter/gopath/src/so/gopath.go and FUNC = main.bar
FILE = so/gopath.go and FUNC = main.bar
PATH = /home/peter/gopath/src/so/gopath.go and FUNC = main.foo
FILE = so/gopath.go and FUNC = main.foo
PATH = /home/peter/gopath/src/so/gopath.go and FUNC = main.main
FILE = so/gopath.go and FUNC = main.main
PATH = /home/peter/go/src/runtime/proc.go and FUNC = runtime.main
FILE = runtime/proc.go and FUNC = runtime.main
于 2018-07-17T14:56:13.690 回答