golang运行时包从构建它的系统中设置文件路径



我有一个简单的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 = %sn", frame.File, frame.Function)
}
}
func foo() {
bar()
}
func main() {
foo()
}

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

我已经在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机器(比如machineB(,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中设置为

/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

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

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


命令进入

GOPATH环境变量列出了查找Go代码的位置。在…上Unix中,该值是一个用冒号分隔的字符串。在Windows上,值为以分号分隔的字符串。在Plan 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 = %sn", frame.File, frame.Function)
fmt.Printf("FILE = %s and FUNC = %sn", 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

最新更新