【发布时间】:2018-07-17 23:44:14
【问题描述】:
我有一个简单的 go 代码,它使用 runtime 包如下:
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()
}
我已将 Go 二进制文件安装在 Ubuntu 机器(例如 机器 A)上的自定义位置 (/home/userA/bin/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 机器(例如 machine B),其中 Go 二进制文件安装在另一个不同的自定义位置(/home/userB/bin/去)。我从 /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
runtime 包似乎在编译期间设置了堆栈帧。
我需要根据 GOPATH 环境变量对文件路径进行一些处理,我在机器 A/home/userA /strong> 并在机器 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
仅为主文件修剪路径前缀。对于任何供应商导入的包或任何本地导入的包,它仍然存在。
【问题讨论】:
-
你只是想手动实现这个吗? stackoverflow.com/questions/45279385/…
-
你可能想要
runtime.GOROOT -
@MichaelHampton,使用
runtime.GOROOT并不能解决我的问题。实际上,我将在机器 A 上编译代码,其中 golang 将安装在某个自定义位置,如/home/userA,但我将在某些机器上运行可执行文件,其中 go 将以其标准安装位置如/usr/bin。所以,使用GOROOT,我将无法成功替换前缀。 -
@JimB 您的解决方案有效,但仅适用于单个文件,不适用于任何导入的包(来自我的项目和任何第 3 方供应商)。我已经根据情况更新了帖子。