你遇到过 go run main.go 或go build main.go 获取到的路径不一样的问题吗?
Go程序的两种执行方式
第一种使用go run xx.go,常用于本地开发
第二种使用go build xx.go 常用于生产环境,通过此命令构建成二进制文件然后上传到服务器再执行
两种方式下带来的问题
使用go run 命令执行
- func getCurrentAbPathByExecutable() string {
- exePath, err := os.Executable()
- if err != nil {
- fmt.Print(err)
- }
- res, _ := filepath.EvalSymlinks(filepath.Dir(exePath))
- return res
- }
- func main() {
- curPath := getCurrentAbPathByExecutable()
- fmt.Println(curPath)
- }
- // go run main.go 输出
- // tmp/go-build4104269073/b001/exe
使用go build 命令执行
- func getCurrentAbPathByExecutable() string {
- exePath, err := os.Executable()
- if err != nil {
- fmt.Print(err)
- }
- res, _ := filepath.EvalSymlinks(filepath.Dir(exePath))
- return res
- }
- func main() {
- curPath := getCurrentAbPathByExecutable()
- fmt.Println(curPath)
- }
- // go build main.go 输出
- // /opt/go_code/demo/path
可以看出,这两种不同的方式生成的路径 是不同的
产生不同路径的原因
这是由于go run会将源代码编译到系统TEMP或TMP环境变量目录中并启动执行;而go build只会在当前目录编译出可执行文件,并不会自动执行。
解决办法
使用 runtime.caller(0)来解决
- func getCurrentAbPathByExecutable() string {
- var absPath string
- _, file, _, ok := runtime.Caller(0)
- if ok {
- absPath = path.Dir(file)
- }
- return absPath
- }
- func main() {
- curPath := getCurrentAbPathByExecutable()
- fmt.Println(curPath)
- }
这样写的话,无论执行go run xx.go 或者 go build xx.go 返回的路径 都是一样的