前言:我覺得java程序員學(xué)golang很容易上手讳嘱。關(guān)于GOROOT幔嗦、GOPATH、GOBIN這些環(huán)境變量的設(shè)置沥潭,我隱約感覺到了java的影子(盡管我是一個C++程序員)邀泉,唯一和java不同的是不能設(shè)置“.”。
另外钝鸽,golang的設(shè)計也很明顯的透露著“約定優(yōu)于配置”的原則汇恤。這在java很多框架里面很常見。golang的環(huán)境變量設(shè)計也是如此拔恰。從android和golang我覺得google喜歡java因谎。
不了解java的C++程序員,可以嘗試全新去理解golang颜懊。
GOROOT
golang安裝路徑财岔。
GOPATH
官方解釋,請google河爹。go工作環(huán)境中常常用到的一個很重要的環(huán)境變量(這種設(shè)計類似java)匠璧。具體用途:go命令常常需要用到的,如go run咸这,go install夷恍, go get等。允許設(shè)置多個路徑炊苫,和各個系統(tǒng)環(huán)境多路徑設(shè)置一樣裁厅,windows用“;”,linux(mac)用“:”分隔侨艾。
在linux(Mac)下执虹,為了方便,一般配置在~/.bash_profile中唠梨。
book:~ wukebing$ vi ~/.bash_profile //編輯
book:~ wukebing$ source ~/.bash_profile //編輯完成后袋励,使立即生效
例如:我的GOPATH設(shè)置(MAC下)
export GOPATH=$HOME/workspace/go
export PATH=$PATH:${GOPATH//://bin:}/bin
export GOBIN=
其中,“export PATH=$PATH:${GOPATH//://bin:}/bin
”為Linux(Mac)下把每個GOPATH下的bin都加入到PATH中当叭。
當(dāng)存在多個路徑時茬故,好像優(yōu)先采用第一個路徑。這個無關(guān)緊要了蚁鳖,只有需要的第三方包(庫)都能正確下載和使用就ok了磺芭。
GOBIN
go install編譯存放路徑。不允許設(shè)置多個路徑醉箕〖叵伲可以為空徙垫。為空時則遵循“約定優(yōu)于配置”原則,可執(zhí)行文件放在各自GOPATH目錄的bin文件夾中(前提是:package main的main函數(shù)文件不能直接放到GOPATH的src下面放棒。
go環(huán)境查看
用go env 可查看當(dāng)前go環(huán)境變量姻报。
GOPATH目錄結(jié)構(gòu)
goWorkSpace // (goWorkSpace為GOPATH目錄)
-- bin // golang編譯可執(zhí)行文件存放路徑,可自動生成间螟。
-- pkg // golang編譯的.a中間文件存放路徑吴旋,可自動生成。
-- src // 源碼路徑厢破。按照golang默認(rèn)約定荣瑟,go run,go install等命令的當(dāng)前工作路徑(即在此路徑下執(zhí)行上述命令)溉奕。
go目錄結(jié)構(gòu)1:
project1 // (project1添加到GOPATH目錄了)
-- bin
-- pkg
-- src
-- models // package
-- controllers // package
-- main.go // package main[注意褂傀,本文所有main.go均指包main的入口函數(shù)main所在文件]
project2 // (project2添加到GOPATH目錄了)
-- bin
-- pkg
-- src
-- models // package
-- controllers // package
-- main.go // package main
package main文件直接在GOPATH目錄到src下。
使用go build可以在src文件夾下編譯生成名為“src”的可執(zhí)行文件加勤。這是golang默認(rèn)約定仙辟。一般我個人不怎么用這個命令。因為它會生成可執(zhí)行文件在src目錄下面鳄梅。
我一般用:go get 和 go install叠国。
go get [main.go所在路徑]
參數(shù) [main.go所在路徑]:可選。相對GOPATH/src路徑戴尸。 缺省是.(src自己)粟焊。可指定src下面的子文件夾路徑孙蒙。
go get會做2件事:1. 從遠(yuǎn)程下載需要用到的包项棠。2.執(zhí)行g(shù)o install。(從這里也可以看出golang處處為了簡潔而遵循的“約定優(yōu)于配置”原則)
go install [main.go所在路徑]
參數(shù) [main.go所在路徑]:可選挎峦。 相對GOPATH/src路徑香追。缺省是.(即當(dāng)前所在目錄或工作目錄)√菇海可指定src下面的子文件夾透典。
go install編譯生成名稱為[main.go父文件夾名]的可執(zhí)行文件,放到GOBIN路徑下顿苇。當(dāng)GOBIN為空時峭咒,默認(rèn)約定是:生成的可執(zhí)行文件放到GOPATH/bin文件夾中。產(chǎn)生的中間文件(.a)放在project/pkg中(沒有變化時纪岁,不重新生成.a)凑队。
我們再看此go目錄結(jié)構(gòu)1,執(zhí)行g(shù)o install(以及go get的第二階段go install)會報錯:
注意:如果不用額外方式改變環(huán)境變量(公司目前用的是sh腳本編譯)幔翰,是編譯不過的顽决。報錯:can’t load package: package .: no buildable Go source files in ***
解決方法1:
曾經(jīng)我也因為這個錯誤感到迷惑短条,認(rèn)為所有都環(huán)境變量都沒有問題导匣。網(wǎng)上也沒怎么看到直接明確都解答才菠。看了一些帖子后贡定,觸類旁通赋访,設(shè)置了GOBIN環(huán)境變量后解決。(好吧缓待,我至今也沒有完整讀過英文官方文檔蚓耽。這種默認(rèn)約定,官方文檔上應(yīng)該有旋炒。)
此解決方法有個弊端步悠,多個project會導(dǎo)致多個GOPATH目錄。多個project下的目錄結(jié)構(gòu)和包一致的話瘫镇,直接編譯會導(dǎo)致編譯問題鼎兽。因為go優(yōu)先使用第一個GOPATH目錄,導(dǎo)致編譯沖突铣除。(當(dāng)然谚咬,你也可以每次手工或腳步修改GOPATH環(huán)境變量,感覺很麻煩尚粘。)不建議多個project直接設(shè)置到茫茫多的GOPATH中择卦。當(dāng)然有解決方法2,我認(rèn)為是標(biāo)準(zhǔn)合理的解決方法郎嫁,就是下面go目錄結(jié)構(gòu)2了秉继。
go目錄結(jié)構(gòu)2:
goWorkSpace // goWorkSpace為GOPATH目錄
-- bin
-- myApp1 // 編譯生成
-- myApp2 // 編譯生成
-- myApp3 // 編譯生成
-- pkg
-- src
-- common 1
-- common 2
-- common utils ...
-- myApp1 // project1
-- models
-- controllers
-- others
-- main.go
-- myApp2 // project2
-- models
-- controllers
-- others
-- main.go
-- myApp3 // project3
-- models
-- controllers
-- others
-- main.go
一個solution里面的多個project或工具組件都并列放在GOPATH的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
這時才是大家都認(rèn)為的澈蝙,把可執(zhí)行程序myApp1、myApp2撵幽、myApp3生成在goWorkSpace/bin下面灯荧。多個GOPATH也就有了上面的“把每個GOPATH下的bin都加入到PATH中”。
提示:相同結(jié)構(gòu)的project下同名包怎么辦盐杂?
有同事在初學(xué)時逗载,習(xí)慣按照go目錄結(jié)構(gòu)1哆窿,了解到go目錄結(jié)構(gòu)2后(以為僅僅是把main放到了子文件夾,其他controllers等包結(jié)構(gòu)不變)厉斟,有這樣的疑惑挚躯。他們原來就有這樣的問題,同時把go目錄加入到GOPATH后擦秽,編譯就出現(xiàn)問題码荔,因為包名和路徑相同(相對GOPATH下的src),go只會優(yōu)先查找第一個符合的GOPATH)感挥。只會每次編譯時手工修改GOPATH缩搅,或?qū)懩_本編譯。(我看著就覺得累触幼,還徒增腳本維護(hù)煩惱硼瓣。)解決方案就是:除了通用的,公有的工具置谦、組件外堂鲤,屬于各個project自己的東西,統(tǒng)統(tǒng)隨著main.go一起移到project目錄下霉祸。go目錄結(jié)構(gòu)2就是這樣的筑累。
導(dǎo)入各個project下的controllers方法:import myApp1/controllers,import myApp2/controllers這樣的丝蹭。go的import查找的是包的路徑慢宗,并不是包名。你只用告訴go奔穿,你的包都放在哪了镜沽,go會從這些路徑下查找有沒有所需要的包。只是大家一般習(xí)慣包名和文件夾名相同贱田,容易誤解缅茉。只需要注意,一個文件夾下只允許有一個包名男摧,允許有子文件夾定義不同的包蔬墩。
import 采用的是相對路徑寫法:路徑是 相對GOROOT和GOPATH下的src。
也可以設(shè)置GOBIN耗拓,而且這時拇颅,由于可執(zhí)行文件名稱不同,也不大容易產(chǎn)生覆蓋(需要避免的時多個GOPATH用相同的“myApp”project名稱乔询。)
具體的還是看個人喜好和實際情況樟插。我個人本地的環(huán)境大致是:
dir
-- goWorkSpace1 // 主要是為了區(qū)分自己的鼓搗的一些東西和工作上的項目
-- goWorkSpace2
-- bin
-- pkg
-- src
-- myApp1
-- .git
-- models
-- controllers
-- main.go
-- myApp2
-- .git
-- models
-- controllers
-- main.go
-- myApp3
-- .git
-- models
-- controllers
-- main.go
也就是我本地是有多個GOPATH路徑的dir/goWorkSpace1、dir/goWorkSpace2。
注意:GOPATH目錄和GOPATH下的src不應(yīng)該添加到源代碼管理中黄锤,而是各個project目錄myApp1搪缨、myApp2、myApp3各自時獨立的進(jìn)行源代碼管理
我一般不設(shè)置GOBIN鸵熟,把每個GOPATH下的bin都加入到PATH中副编。
個人理解,有任何問題旅赢,歡迎指正齿桃。