1.go modules的基本介紹
1.1 環境變量
export GO111MODULE="on"
export GOPATH="/home/go-project/"
export GOPROXY="https://goproxy.cn,direct"
export GONOPROXY="git.example.com,x1"
export GONOSUMDB="git.example.com,x1"
export GOPRIVATE="git.example.com,x1"
export GOSUMDB="sum.golang.org"
1) GO111MODULE
go語言提供GO111MODULE環境變量三個值,用於GO111MODULE的開關:
- auto:只要項目中包含了
go.mod這個文件,就啟動該項目的go modules,在 Go1.11 至 Go1.14 中仍然是默認值。 - on:啟動
go modules - off:關閉
go modules
2) GOPROXY
go env中默認的代理是 GOPROXY="https://proxy.golang.org,direct" ,但是在國內是無法訪問的,這里需要設置成國內的代理地址 GOPROXY="https://goproxy.cn,direct"
GOPROXY的值是一個以英文逗號 “,” 分割的 Go 模塊代理列表,允許設置多個模塊代理,假設你不想使用,也可以將其設置為 “off” ,這將會禁止 Go 在后續操作中使用任何 Go 模塊代理。
direct
實際上 “direct” 是一個特殊指示符,用於指示 Go 回源到模塊版本的源地址去抓取(比如 GitHub 等),場景如下:當值列表中上一個 Go 模塊代理返回 404 或 410 錯誤時,Go 自動嘗試列表中的下一個,遇見 “direct” 時回源,也就是回到源地址去抓取,而遇見 EOF 時終止並拋出類似 “invalid version: unknown revision…” 的錯誤。
3)GONOPROXY、GONOSUMDB、GOPRIVATE
這三個環境變量都是用在當前項目依賴了私有模塊,例如像是你公司的私有 git 倉庫,又或是 github 中的私有庫,都是屬於私有模塊,都是要進行設置的,否則會拉取失敗。對於一些自己的私有模塊代碼,需要在GOPRIVATE上設置,在拉取時會提示輸入用戶名和密碼。
可以設置多個,用英文的逗號分隔開;或者用通配符等
export GOPRIVATE="git.example.com,github.com/eddycjy/mquote"
export GOPRIVATE="*.example.com" # 通配example.com的域名
1.2 提供的命令
在go環境的shell中執行 go mod help 查看命令和說明。
Usage: go mod <command> [arguments] The commands are: download 下載模塊到本地緩存,緩存路徑是$GOPATH/pkg/mod/cacheedit 是提供了命令版編輯go.mod的功能,例如go mod edit -fmt go.mod會格式化go.modgraph 把模塊之間的依賴圖顯示出來 init 初始化模塊(例如把原本dep管理的依賴關系轉換過來) tidy 增加缺失的包,移除沒用的包 vendor 把依賴拷貝到vendor/目錄下 verify 確認依賴關系 why 解釋為什么需要包和模塊2.go modules的基本使用
2.go modules的基本使用
開啟go modules后,就可以創建項目並且生成mod文件,來管理項目的所有依賴了。以下是go env環境的配置:
GO111MODULE="auto" GOARCH="amd64" GOBIN="/go/bin/" GOCACHE="/root/.cache/go-build" GOENV="/root/.config/go/env" GOEXE="" GOFLAGS="" GOHOSTARCH="amd64" GOHOSTOS="linux" GOINSECURE="" GONOPROXY="" GONOSUMDB="" GOOS="linux" GOPATH="/home/go-project/" GOPRIVATE="" GOPROXY="https://goproxy.cn,direct" GOROOT="/go" GOSUMDB="sum.golang.org" GOTMPDIR="" GOTOOLDIR="/go/pkg/tool/linux_amd64" GCCGO="gccgo" AR="ar" CC="gcc" CXX="g++" CGO_ENABLED="1" GOMOD="" CGO_CFLAGS="-g -O2" CGO_CPPFLAGS="" CGO_CXXFLAGS="-g -O2" CGO_FFLAGS="-g -O2" CGO_LDFLAGS="-g -O2" PKG_CONFIG="pkg-config" GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build940953411=/tmp/go-build -gno-record-gcc-switches"
設置了GOPATH為 /home/go-project/ ,並且代理指向了國內的代理地址,防止國外鏡像無法訪問的情況。
2.1 初始化項目
在$GOPATH目錄下創建一個新的項目example.com/mycount/hello,example.com模擬github.com,mycount模擬賬號,hello是最終的項目名稱。目錄和文件結構:
2.1.1 初始化.mod文件
在hello目錄下執行 go mod init example.com/mycount/hello 初始化hello項目的mod文件,如下:
執行完初始化操作后生成了一個go.mod的文件,里面只記錄了2行:
- module:用於定義當前項目的模塊路徑
- go:用於標識當前模塊的 Go 語言版本,值為初始化模塊時的版本,目前來看還只是個標識作用
2.1.2 簡單一個示例
在hello目錄下寫一個main.go的文件,里面用了一個第三方的庫。
package main import ( "net/http" "github.com/gin-gonic/gin" "github.com/json-iterator/go" ) type resp struct { Status int `json:"status"` Message string `json:"message"` } func main() { router := gin.Default() router.GET("/", hello()) if err := router.Run(":6060"); err != nil { panic(err) } } func hello() gin.HandlerFunc { return func(context *gin.Context) { strResp, _ := jsoniter.MarshalToString(resp{ Status: http.StatusOK, Message: "success", }) context.String(http.StatusOK, strResp) } }
在hello目錄下執行go get命令,拉取依賴庫:
拉取依賴之后生成了一個go.mod和go.sum文件,go.mod文件:
go.sum的內容:
同時在$GOPATH目錄下多了一個pkg文件,里面有拉取的文件依賴。這個文件是一個全局的緩存。
2.1.3 go modules的go get
在拉取項目依賴時,你會發現拉取的過程總共分為了三大步,分別是 finding(發現)、downloading(下載)以及 extracting(提取), 並且在拉取信息上一共分為了三段內容:
需要注意的是,所拉取版本的 commit 時間是以UTC時區為准,而並非本地時區,同時我們會發現我們 go get 命令所拉取到的版本是 v0.0.0,這是因為我們是直接執行 go get -u 獲取的,並沒有指定任何的版本信息,由 Go modules 自行按照內部規則進行選擇。
那么我想選擇具體版本應當如何執行呢,如下:

