以 gin-blog 为例,当我们在项目根目录下,执行 go run main.go 时能够正常运行(go build也是正常的)
[$ gin-blog]# go run main.go
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET /api/v1/tags --> gin-blog/routers/api/v1.GetTags (3 handlers)
...
那么在不同的目录层级下,不同的方式运行,又是怎么样的呢,带着我们的疑问去学习
问题
1、 go run 我们上移目录层级,到 $GOPATH/src 下,执行 go run gin-blog/main.go
[$ src]# go run gin-blog/main.go
2018/03/12 16:06:13 Fail to parse 'conf/app.ini': open conf/app.ini: no such file or directory
exit status 1
2、 go build,执行 ./gin-blog/main
这时候你要打一个大大的问号,就是我的程序读取到什么地方去了
我们通过分析得知,Golang的相对路径是相对于执行命令时的目录;自然也就读取不到了
思考
既然已经知道问题的所在点,我们就可以寻思做点什么 : )
我们想到相对路径是相对执行命令的目录,那么我们获取可执行文件的地址,拼接起来不就好了吗?
实践
我们编写获取当前可执行文件路径的方法
将其放到启动代码处查看路径
我们分别执行以下两个命令,查看输出结果 1、 go run
2、 go build
剖析
我们聚焦在 go run 的输出结果上,发现它是一个临时文件的地址,这是为什么呢?
在go help run中,我们可以看到
也就是 go run 执行时会将文件放到 /tmp/go-build... 目录下,编译并运行
因此go run main.go出现/tmp/go-build962610262/b001/exe结果也不奇怪了,因为它已经跑到临时目录下去执行可执行文件了
这就已经很清楚了,那么我们想想,会出现哪些问题呢
依赖相对路径的文件,出现路径出错的问题
go run 和 go build 不一样,一个到临时目录下执行,一个可手动在编译后的目录下执行,路径的处理方式会不同
不断go run,不断产生新的临时文件
这其实就是根本原因了,因为 go run 和 go build 的编译文件执行路径并不同,执行的层级也有可能不一样,自然而然就出现各种读取不到的奇怪问题了
$ go run main.go
2018/03/12 18:45:40 /tmp/go-build962610262/b001/exe
$ ./main
2018/03/12 18:49:44 $GOPATH/src/gin-blog
Run compiles and runs the main package comprising the named Go source files.
A Go source file is defined to be a file ending in a literal ".go" suffix.