douju1928 2018-07-16 19:25
浏览 63

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

I've a simple go code, that uses the runtime package as follows:

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
", frame.File, frame.Function)
    }
}

func foo() {
    bar()
}

func main() {
    foo()
}

I've Go binary installed in a custom location (/home/userA/bin/go) on a Ubuntu machine (say machine A)

I've compiled it on machine A and ran the executable on the same machine to get the output:

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

Now I copied the compiled executable to another Ubuntu machine (say machine B) where Go binary was installed in another different custom location (/home/userB/bin/go). I ran the executable from /home/userB. But this time also, I got the same output as before:

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

It seems that the runtime package sets the stack-frames during compilation time.

I need to do some processing on the file paths based on GOPATH environment variable, which I've set as /home/userA on machine A and as /home/userB on machine B.

I need to strip the GOPATH part from each of those file paths. I'm doing it with this simple function call: strings.Replace(frame.File, GOPATH, "", 1)

But, because of this behaviour of the runtime package, the strings.Replace function fails to replace the initial portion of the file paths on machine B.

Any idea on how to accomplish this on machine B ?

UPDATE

Following the suggestion from @JimB, I've built the project with

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

Now, running the executable on the same machine gives output as:

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

The path prefix is trimmed only for the main file. It's still there for any vendor imported package or any locally imported package.

  • 写回答

1条回答 默认 最新

  • duanjiwu0324 2018-07-17 14:56
    关注

    What are you tring to accomplish? The XY problem is asking about your attempted solution rather than your actual problem: The XY Problem.


    Command go

    The GOPATH environment variable lists places to look for Go code. On Unix, the value is a colon-separated string. On Windows, the value is a semicolon-separated string. On Plan 9, the value is a list.


    GOPATH is an artifact of the Go tools. It is not covered by the Go language compatibility guarantees.

    What should happen if the GOPATH list has more than one element?


    Does this work for you?

    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
    ", frame.File, frame.Function)
            fmt.Printf("FILE = %s and FUNC = %s
    ", srcFile(frame.File), frame.Function)
        }
    }
    
    func foo() {
        bar()
    }
    
    func main() {
        foo()
    }
    

    Output:

    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
    
    评论

报告相同问题?

悬赏问题

  • ¥35 平滑拟合曲线该如何生成
  • ¥100 c语言,请帮蒟蒻写一个题的范例作参考
  • ¥15 名为“Product”的列已属于此 DataTable
  • ¥15 安卓adb backup备份应用数据失败
  • ¥15 eclipse运行项目时遇到的问题
  • ¥15 关于#c##的问题:最近需要用CAT工具Trados进行一些开发
  • ¥15 南大pa1 小游戏没有界面,并且报了如下错误,尝试过换显卡驱动,但是好像不行
  • ¥15 自己瞎改改,结果现在又运行不了了
  • ¥15 链式存储应该如何解决
  • ¥15 没有证书,nginx怎么反向代理到只能接受https的公网网站