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

时间:2018-07-16 19:25:02

标签: go runtime elf gopath

我有一个简单的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计算机(例如计算机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

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

我需要基于 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

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

1 个答案:

答案 0 :(得分:0)

您打算完成什么? XY问题是在询问您尝试的解决方案,而不是实际的问题:The XY Problem


  

Command go

     

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