GOROOT、GOPATH、GOBIN、project目录
前言:我觉得java程序员学golang很容易上手。关于GOROOT、GOPATH、GOBIN这些环境变量的设置,我隐约感觉到了java的影子(尽管我是一个C++程序员),唯一和java不同的是不能设置“.”。
另外,golang的设计也很明显的透露着“约定优于配置”的原则。这在java很多框架里面很常见。golang的环境变量设计也是如此。从android和golang我觉得google喜欢java。
不了解java的C++程序员,可以尝试全新去理解golang。
GOROOT
golang安装路径。
GOPATH
官方解释,请google。go工作环境中常常用到的一个很重要的环境变量(这种设计类似java)。具体用途:go命令常常需要用到的,如go run,go install, go get等。允许设置多个路径,和各个系统环境多路径设置一样,windows用“;”,linux(mac)用“:”分隔。
在linux(Mac)下,为了方便,一般配置在~/.bash_profile中。
book:~ wukebing$ vi ~/.bash_profile //编辑
book:~ wukebing$ source ~/.bash_profile //编辑完成后,使立即生效
例如:我的GOPATH设置(MAC下)
export GOPATH=$HOME/work/solution1/go:$HOME/work/solution1/workspace/core-server:$HOME/work/solution1/workspace/api-server:$HOME/work/solution1/workspace/test export PATH=$PATH:${GOPATH//://bin:}/bin export GOBIN=
其中,“export PATH=$PATH:${GOPATH//://bin:}/bin
”为Linux(Mac)下多个project的PATH设置方法。把每个project下的bin都加入到PATH中。
当存在多个路径时,好像优先采用第一个路径。这个无关紧要了,只有需要的第三方包(库)都能正确下载和使用就ok了。
GOBIN
go install编译存放路径。不允许设置多个路径。可以为空。为空时则遵循“约定优于配置”原则,可执行文件放在project目录的bin文件夹中(前提是:package main的main函数文件不能直接放到project的src下面。
go环境查看
用go env 可查看当前go环境变量。
project目录结构
project -- bin // golang编译可执行文件存放路径,可自动生成。 -- pkg // golang编译的.a中间文件存放路径,可自动生成。 -- src // 源码路径。按照golang默认约定,go run,go install等命令的当前工作路径(即在此路径下执行上述命令)。
project目录结构1:
project -- bin -- pkg -- src -- common -- models package -- controllers package -- main.go // package main的main函数文件
package main的main函数文件直接在project到src下。
使用go build可以在src文件夹下编译生成名为“src”的可执行文件。这是golang默认约定。一般我个人不怎么用这个命令。因为它会生成可执行文件在src目录下面。
我一般用:go get 和 go install。
go get [文件夹名]
参数 [文件夹名]:可选。 缺省是src自己。可指定src下面的子文件夹。
go get会做2件事:1. 从远程下载需要用到的包。2.执行go install。(从这里也可以看出golang处处为了简洁而遵循的“约定优于配置”原则)
go install [文件夹名]
参数 [文件夹名]:可选。 缺省是src自己。可指定src下面的子文件夹。
go install编译生成名称为[文件夹名]的可执行文件,放到GOBIN路径下。当GOBIN为空时,默认约定是:生成的可执行文件放到project/bin文件夹中。产生的中间文件(.a)放在project/pkg中(没有变化时,不重新生成.a)。
我们再看此project目录,执行go install(以及go get的第二阶段go install)会报错:
如果不用额外方式改变环境变量(公司目前用的是sh脚本编译),是编译不过的。报错:can’t load package: package .: no buildable Go source files in *
解决方法1:
曾经我也因为这个错误感到迷惑,认为所有都环境变量都没有问题。网上也没怎么看到直接明确都解答。看了一些帖子后,触类旁通,设置了GOBIN环境变量后解决。(好吧,我至今也没有完整读过英文官方文档。这种默认约定,官方文档上应该有。)
此解决方法有个弊端,多个project,最后编译都可执行文件会覆盖前面的。而且,多个可执行文件必然时按多个project思路去做。很多人好像也不建议多个project和茫茫多的GOPATH。当然,你看了后面,似乎有种感觉,google也倾向一个project。当然有解决方法2,我认为也是google推荐的解决方法(从设计原则中感觉),这就是project目录结构2了。
project目录结构2:
project -- bin -- myApp1 // 编译生成 -- myApp2 // 编译生成 -- myApp3 // 编译生成 -- pkg -- src -- common 1 -- common 2 -- common utils ... -- myApp1 -- models -- controllers -- others -- main.go // package main的main函数文件 -- myApp2 -- models -- controllers -- others -- main.go // package main的main函数文件 -- myApp3 -- models -- controllers -- others -- main.go // package main的main函数文件
一个solution里面的多个project或工具组件都并列放在src下,如myApp1,myApp2,myApp3,common utils。
这时,GOBIN可以为空,编译时,可以如下:
go install myApp1 或 go get myApp1
go install myApp2 或 go get myApp2
go install myApp3 或 go get myApp3
这时才是大家都认为的,把可执行程序myApp1、myApp2、myApp3生成在project/bin下面。多个project也就有了上面的“把每个project下的bin都加入到PATH中”。
提示:不同project下controllers等包怎么样?
有同事在初学时,习惯按照project目录结构1,了解到project目录结构2后(以为仅仅是把main放到了子文件夹,其他controllers等包结构不变),有这样的疑惑。他们原来就有这样的问题,同时把project目录加入到GOPATH后,编译就出现问题,因为包名和路径相同(相对project),go只会优先查找第一个符合的GOPATH)。只会每次编译时手工修改GOPATH,或写脚本编译。(我看着就觉得累,还徒增脚本维护烦恼。)解决方案就是:除了通用的,公有的工具、组件外,属于各个project自己的东西,统统随着main.go一起移到project目录下。project目录结构2就是这样的。
引用各个project下的controllers方法:import myApp1/controllers,import myApp2/controllers这样的。go的import查找的是包的路径,并不是包名。你只用告诉go,你的包都放在哪了,go会从这些路径下查找有没有所需要的包。只是大家一般习惯包名和文件夹名相同,容易误解。
import 采用的是相对路径写法:相对GOROOT和GOPATH下的src。
也可以设置GOBIN,而且这时,由于可执行文件名称不同,也不大容易产生覆盖(需要避免的时多个project用相同的“myApp”名称。)
从这种project目录结构,似乎可以看出,google似乎推荐大家所说的,避免设置多个GOPATH。
具体的还是看个人喜好和实际情况。我个人本地的环境大致是:
dir -- go // 最早配置环境或有些工具需要用到,就设置了这么个项目无关go目录。这个目录也就一直这么保存了。 -- bin -- pkg -- src -- solution1 // 区分工作上不同的项目以及自己的鼓捣学习的一些东西 -- solution2 -- myProject -- bin -- pkg -- src -- common -- myApp1 -- models -- controllers -- main.go // package main的main函数文件 -- myApp2 -- models -- controllers -- main.go // package main的main函数文件 -- myApp3 -- models -- controllers -- main.go // package main的main函数文件
也就是我本地是有多个GOPATH路径的dir/go、dir/solution1、dir/solution2。
我一般不设置GOBIN,把每个project下的bin都加入到PATH中。
个人理解,有任何问题,欢迎指正。