我們可以輸入go env
查看我們的go環(huán)境變量
GOPATH="/Users/inf/go"
GOROOT="/usr/local/go"
GO111MODULE="auto"
GOPATH
GOPATH 是 Go語(yǔ)言中使用的一個(gè)環(huán)境變量,它使用絕對(duì)路徑提供項(xiàng)目的工作目錄仔夺。
- 工作目錄:一個(gè)工程開(kāi)發(fā)的相對(duì)參考目錄琐脏。工作區(qū)的概念與工作目錄的概念也是類(lèi)似的。如果不使用工作目錄的概念缸兔,在多人開(kāi)發(fā)時(shí)日裙,每個(gè)人有一套自己的目錄結(jié)構(gòu),讀取配置文件的位置不統(tǒng)一惰蜜,輸出的二進(jìn)制運(yùn)行文件也不統(tǒng)一昂拂,這樣會(huì)導(dǎo)致開(kāi)發(fā)的標(biāo)準(zhǔn)不統(tǒng)一,影響開(kāi)發(fā)效率抛猖。
命令行輸出我們可以看到go的工作目錄GOPATH默認(rèn)為/Users/xxx/go/
使用GOPATH的工程結(jié)構(gòu)
在 GOPATH 指定的工作目錄下格侯,代碼總是會(huì)保存在 $GOPATH/src
目錄下。在工程經(jīng)過(guò) go build
财著、go install
或 go get
等指令后联四,會(huì)將產(chǎn)生的二進(jìn)制可執(zhí)行文件放在 $GOPATH/bin
目錄下,生成的中間緩存文件會(huì)被保存在 $GOPATH/pkg
下撑教。
如果需要將整個(gè)源碼添加到版本管理工具(Version Control System朝墩,VCS)中時(shí),只需要添加 $GOPATH/src
目錄的源碼即可伟姐。bin 和 pkg 目錄的內(nèi)容都可以由 src 目錄生成收苏。
設(shè)置和使用GOPATH
我們可以使用命令
export GOPATH=`pwd`
選擇一個(gè)目錄亿卤,在目錄中的命令行中執(zhí)行下面的指令:設(shè)置當(dāng)前目錄為GOPATH
該指令中的 pwd
將輸出當(dāng)前的目錄,使用反引號(hào)`將 pwd
指令括起來(lái)表示命令行替換鹿霸,也就是說(shuō)排吴,使用 `pwd` 將獲得 pwd 返回的當(dāng)前目錄的值。例如懦鼠,假設(shè)你的當(dāng)前目錄是“/Users/xxx/go”钻哩,那么使用pwd
將獲得返回值“/Users/xxx/go”。
使用 export 指令可以將當(dāng)前目錄的值設(shè)置到環(huán)境變量 GOPATH中葛闷。
網(wǎng)上建議大家無(wú)論是使用命令行或者使用集成開(kāi)發(fā)環(huán)境編譯 Go 源碼時(shí)憋槐,GOPATH 跟隨項(xiàng)目設(shè)定。在 Jetbrains 公司的 GoLand 集成開(kāi)發(fā)環(huán)境(IDE)中的 GOPATH 設(shè)置分為全局 GOPATH 和項(xiàng)目 GOPATH淑趾,如下圖所示
Global GOPATH 代表全局 GOPATH,一般來(lái)源于系統(tǒng)環(huán)境變量中的 GOPATH忧陪;Project GOPATH 代表項(xiàng)目所使用的 GOPATH扣泊,該設(shè)置會(huì)被保存在工作目錄的 .idea 目錄下,不會(huì)被設(shè)置到環(huán)境變量的 GOPATH 中嘶摊,但會(huì)在編譯時(shí)使用到這個(gè)目錄延蟹。建議在開(kāi)發(fā)時(shí)只填寫(xiě)項(xiàng)目 GOPATH,每一個(gè)項(xiàng)目盡量只設(shè)置一個(gè) GOPATH叶堆,不使用多個(gè) GOPATH 和全局的 GOPATH阱飘。
GOROOT
GOROOT就是我們Go語(yǔ)言的安裝路徑。我這里是/usr/local/go
打開(kāi)這個(gè)文件夾虱颗,同樣可以看到
src, bin, pkg三個(gè)文件夾沥匈,
標(biāo)準(zhǔn)的Go語(yǔ)言代碼庫(kù)中包含了大量的包,并且在安裝 Go 的時(shí)候多數(shù)會(huì)自動(dòng)安裝到系統(tǒng)中忘渔。我們可以在 $GOROOT/src/pkg 目錄中查看這些包高帖。當(dāng)我們 import內(nèi)置包的時(shí)候,并不需要額外安裝,當(dāng)程序運(yùn)行時(shí)畦粮,會(huì)先去GOROOT下找相應(yīng)的包來(lái)運(yùn)行散址。
我們可以在其他隨便一個(gè)文件夾下運(yùn)行下運(yùn)行mian.go
比如我新建了一個(gè)hello文件夾,
//main.go
package main
?
import "fmt"
?
func main() {
fmt.Println("Hello World")
}
會(huì)成功輸出Helo World宣赔,go run其實(shí)幫你將程序進(jìn)行編譯并生成可執(zhí)行文件预麸,而編譯文件和執(zhí)行文件實(shí)際上存在在一個(gè)暫存資料夾里面,當(dāng)運(yùn)行完這個(gè)程序就會(huì)自動(dòng)刪除儒将。該指令可以相乘類(lèi)似直譯的方式運(yùn)行吏祸,而不需要其他任何環(huán)境設(shè)定。
但如果
要引入hello.go椅棺,或者import 某個(gè)Github上的包犁罩,就會(huì)報(bào)錯(cuò)
import (
"hello"
)
?
func main() {
test1()
}
// main.go:10:3: cannot find package "hello" in any of:
// /usr/local/go/src/hello (from $GOROOT)
// /Users/inf/go/src/hello (from $GOPATH)
1齐蔽、 當(dāng)執(zhí)行g(shù)olang程序,需要獲取import的包時(shí)床估,編譯器回先去GOROOT路徑下的src文件夾找有沒(méi)有我們?cè)诔绦蛑衖mport的包
2含滴、如果在GOROOT下沒(méi)有找到,就會(huì)去GOPATH下src下找這個(gè)包
所以只要GOROOT跟GOPATH下都沒(méi)找到包的話就會(huì)報(bào)錯(cuò)
go run, go build, go install
go run
go run 編譯并直接運(yùn)行程序丐巫,它會(huì)產(chǎn)生一個(gè)臨時(shí)文件(但不會(huì)生成 .exe 文件)谈况,直接在命令行輸出程序執(zhí)行結(jié)果,方便用戶調(diào)試递胧,產(chǎn)生執(zhí)行結(jié)果后就會(huì)自動(dòng)刪除碑韵。
go build
go build 用于測(cè)試編譯包,主要檢查是否會(huì)有編譯錯(cuò)誤缎脾,如果是一個(gè)可執(zhí)行文件的源碼(即是 main 包)祝闻,就會(huì)直接生成一個(gè)可執(zhí)行文件。
go build main.go
這樣會(huì)在當(dāng)前目錄下產(chǎn)生一個(gè)名稱(chēng)為mian的可執(zhí)行文件遗菠。也可以在build后面寫(xiě)專(zhuān)門(mén)的項(xiàng)目名稱(chēng)联喘,執(zhí)行該命令會(huì)自動(dòng)在當(dāng)前文件夾下找package為mian,并且有main function的go文件辙纬,再編譯成可執(zhí)行文件
也可以使用下面的命令指定build出來(lái)的可執(zhí)行文件放在哪里
go build -o bin/main src/demo/main.go
-o后面的第一個(gè)參數(shù)表示生產(chǎn)的可執(zhí)行文件的路徑以及名稱(chēng)豁遭,第二個(gè)參數(shù)代表要編譯的go文件的路徑。
按照慣例贺拣,GOPATH下bin文件夾存放build出來(lái)的可執(zhí)行文件蓖谢。
go build有個(gè)缺點(diǎn)就是每次編譯go文件比較沒(méi)有效率,當(dāng)項(xiàng)目架構(gòu)越來(lái)越大build的速度也越來(lái)越慢譬涡。
go install
go install 的作用有兩步:第一步是編譯導(dǎo)入的包文件闪幽,所有導(dǎo)入的包文件編譯完才會(huì)編譯主程序;第二步是將編譯后生成的可執(zhí)行文件放到 bin 目錄下($GOPATH/bin
)昂儒,編譯后的包文件放到 pkg 目錄下($GOPATH/pkg
)沟使。
go install 做兩件事情,
- 將package編譯成.a file
- 如果是main 包則編譯成可執(zhí)行文件
有了第一項(xiàng)功能渊跋,下次編譯時(shí)候就不會(huì)將包的程序碼重新編譯腊嗡,而是直接用編譯好的.a file。而.a file就位于GOPATH/pkg里面拾酝。
來(lái)看一個(gè)例子
GOPATH/src下新建兩個(gè)項(xiàng)目mypkg和mytest燕少,分別新建兩個(gè)go文件
mypkg.go
package mypkg
?
import "fmt"
?
func MyFunc() {
fmt.Println("MyFunc")
}
mytest.go
package main
?
import (
"mypkg"
)
?
func main() {
mypkg.MyFunc()
}
mytest.go中用了import了mypkg的包,而可以通過(guò)install指令將mypkg編譯成.a file
go install mypkg
可以發(fā)現(xiàn)在GOPATH/darwin_amd64/mypkg.a
有該文件
darwin_amd64是由GOOS和GOARCH兩個(gè)環(huán)境變量所組合合成的
GOPATH缺點(diǎn)
當(dāng)我們的第三方包不是官方庫(kù)時(shí)都要放在GOPATH/src下才可以使用
我們通常使用go get指令來(lái)獲取第三方的包
go get github.com/gin-gonic/gin
go get 最長(zhǎng)用在當(dāng)我們想用別人公開(kāi)在github上的包蒿囤,可以幫我們從網(wǎng)上clone到GOPATH/src下客们。
是不是聽(tīng)起來(lái)很方便?會(huì)讓src下的項(xiàng)目變得很復(fù)雜,除了有自己的項(xiàng)目還有其他第三方庫(kù)的項(xiàng)目底挫。
在如果恒傻,我們的不同的項(xiàng)目采用的第三方庫(kù)是不同的版本怎么辦,go1.11以前是要設(shè)頂多組不同的GOPATH,雖然go社區(qū)也有開(kāi)發(fā)相對(duì)應(yīng)的包管理工具建邓,如Vender,Dep來(lái)結(jié)局該問(wèn)題盈厘,但它們都不是官方的。
GOMOD
Go Modules很像java的maven官边,將第三方的庫(kù)放在本地的空間沸手,但它不是自動(dòng)的下載包的
如下命令開(kāi)啟和關(guān)閉go mod
go env -w GO111MODULE=on 打開(kāi)
go env -w GO111MODULE=off 關(guān)閉
GO111MODULE有三個(gè)不同的值
-
auto
- 當(dāng)存在 go.mod 文件時(shí)或處于 GOPATH 外, 其行為均會(huì)等同于于 GO111MODULE=on注簿。這意味著在 Go 1.13 及之后的版本你可以將所有的代碼倉(cāng)庫(kù)均存儲(chǔ)在 GOPATH 下契吉。
- 當(dāng)處于 GOPATH 內(nèi)且沒(méi)有 go.mod 文件存在時(shí)其行為會(huì)等同于 GO111MODULE=off。
on
即使項(xiàng)目在您的 GOPATH 中诡渴,GO111MODULE = on 仍將強(qiáng)制使用 Go 模塊捐晶。需要 go.mod 正常工作off
強(qiáng)制 Go 表現(xiàn)出 GOPATH 方式,即使在 GOPATH 之外妄辩。
下載下來(lái)的第三方庫(kù)在哪呢租悄?其實(shí)就在GOPATH/pkg/mod文件夾里面
接下來(lái)就是和maven很像的操作了
src下新建一個(gè)文件夾modtest
該文件夾下執(zhí)行
go mod init <module name>
<module name>可填可不填,不填的話就是采用項(xiàng)目文件夾的名稱(chēng),執(zhí)行后會(huì)出現(xiàn)一個(gè)go.mod的文件
module modtest
go 1.15
go.mod 提供了module, require、replace和exclude 四個(gè)命令
module 語(yǔ)句指定包的名字(路徑)
require 語(yǔ)句指定的依賴(lài)項(xiàng)模塊,默認(rèn)最新版恩袱,可以指定版本號(hào)
replace 語(yǔ)句可以替換依賴(lài)項(xiàng)模塊
exclude 語(yǔ)句可以忽略依賴(lài)項(xiàng)模塊
還有個(gè)go 命令定義go語(yǔ)言的版本
添加一個(gè),假設(shè)我要引入github.com/gin-gonic/gin v1.5.0這個(gè)包
module modtest
go 1.15
require github.com/gin-gonic/gin v1.5.0
在執(zhí)行
go mod download
會(huì)發(fā)現(xiàn)當(dāng)前文件夾下多了個(gè)go.sum的文件胶哲,該文件基本上用來(lái)記錄包版本的關(guān)系畔塔,不怎么需要理會(huì)。需要的包裝在GOPATH/pkg/mod文件夾下
之后運(yùn)行
go run main.go
GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[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] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080
這個(gè)就是在local 8080 port開(kāi)啟一個(gè)web server~
當(dāng)然也可以不執(zhí)行g(shù)o mod download而直接運(yùn)行g(shù)o build或者go install也會(huì)自動(dòng)下載包
還有一種方法可以直接下載
使用go get命令
go get github.com/gin-gonic/gin@v1.6.3
或者require指定版本,執(zhí)行g(shù)o get指令鸯屿。和download是一樣的澈吨。
只要有開(kāi)啟gomod功能,go get就不會(huì)再src下放package寄摆,而是會(huì)放在/pkg/mod里面谅辣,并且mod會(huì)寫(xiě)好引入。也就不需要go mod download了