Golang中,runtime.Caller(skip),为什么会保留编译器变量?

我有一个需求,就是在其他目录下执行非当前目录下的go文件,要求输出go文件的所在绝对路径,我才用的方法是runtime.Caller(0),获取文件位置,但是发现,如果我在A目录下编译的go文件,mv到B目录下之后,go文件依旧输出A的目录,具体效果如下:

clipboard.png

test是在/app/projectGo下编译生成的,然后mv到了/app/projectGo/inner下,然而我在inner目录下执行./test的时候他依旧输出/app/projectGo这个目录,test.go源码如下

package main

import (
    "fmt"
    "runtime"
)

func main() {
    _, currentPath, _, _ := runtime.Caller(2)
    fmt.Println(currentPath)
}

请问为什么?另外,如果要实现这个需求要怎么做?

阅读 5.2k
3 个回答

runtime.Caller 就是用于打印调用栈信息的,你的需求和它没关系。当你需要调试代码时,可以使用下它。

开始说你的需求。

首先,要理解一点,Go 不是解释型语言,它的路径不是 .go 文件的路径,而是编译出来的可执行文件的路径。

举个例子吧。

假设有个 Python 程序,在 /data/release/index.py,那么程序获取的路径就是 py 文件的路径。

但是如果是 Go 呢?直接先看代码:

package main

import (
    "fmt"
    "os"
)

func main() {
    ePath, err := os.Executable()
    if err != nil {
        panic(err)
    }

    // 全路径
    fmt.Println(ePath)
    // 所在目录
    fmt.Println("file directory", path.Dir(ePath))
}

通过 go build 编译成可执行二进制文件,执行文件看看,这个时候获取到的路径就是可执行文件的路径了。

为什么不用 go run 执行呢?

如果你用 go run main.go,它中间是会生成一个临时的可执行文件,这时候通过代码获取的路径就是生成的那个可执行文件的路径。如果想知道这个临时路径在哪里可以看看我的一篇文章,Go 笔记之详解 Go 的编译执行流程,如果文章看懂了,可以帮忙点个赞,感谢?。

我猜你想获取的是当前工作目录,应该使用os.Getwd()

package main

import (
    "fmt"
    "os"
)

func main() {
    currentPath, _ := os.Getwd()
    fmt.Println(currentPath)
}

其实我想获取的是这个文件的静态目录,也就是说无论我cd到哪一层级目录,/a/b/c/d/test.go都可以输出这个test.go的绝对路径,而不是我执行的路径

1 篇内容引用
推荐问题
宣传栏