go包管理速通,一篇文章就夠了,再也不用擔心因為不會導包被辭退

白澤來了發表於2022-01-15

前言

image-20220114204429203

最近在看一些go語言相關的書,發現了一個有意思的事情:其中一本書最新印刷的版本是2017年3月,而golang包管理的後起之秀go module伴隨go1.11於2018年8月誕生——因此,書裡沒有。

有感於golang發展速度之快,且當下專案中go modulego vendor(go1.5之後一個熱門的包管理工具)交織,甚至時不時看到go path包管理模式在一些文章中死灰復燃,我想有必要正確梳理一下其中的緣由,以便大家選擇合適的包管理模式。

白澤,無腦選擇go module不好嗎?過時的東西有必要學嗎?

事實上,我認為你可以不用它,但是你得懂為什麼這種技術不推薦甚至被棄用,而且你很難定義什麼是過時的技術,比如我專案中就用到了vendor。很多golang學習者可能有其他語言的基礎,上手go也很快,java有maven,那go必然也有xx包管理工具吧!開啟搜尋引擎輸入go快速入門,安裝與專案構建,有的人查到了go path,有的人查到了govendor、有的人則是go module

這也是我想寫一篇文章總結的原因(萬一有一天go module也不推薦使用了呢!這種演變的思路值得了解),看過之後保證你能看懂別人文章中寫的GOPATH/src、GOPATH/bin、GOPATH/pkg/mod云云,我們開始。

兩個命令

go install xxx(下載xxx第三方二進位制可執行檔案

go get xxx(下載xxx第三方依賴包

下載可執行檔案/第三方依賴到本地哪裡?不同的包管理工具不同,下面講。

兩個路徑

  • GOROOT:go的安裝目錄,類似java的jdk,存放一些內建的開發包和工具。
  • GOPATH:go指定的工作空間,用於儲存go專案的程式碼和第三方依賴包。
# mac可以通過go env檢視go相關的環境變數,windows類似
go env
GOROOT="/usr/local/go"
GOPATH="/Users/baize/GolandProjects/"

三個包管理工具

go path【不推薦使用】

go path是最早的依賴包管理方式(Go1.0),啟用GOPATH模式(注意區分GOPATH模式和GOPATH路徑,這是兩個語境),要求將所有工程程式碼要求放在GOPATH/src目錄下。在工程經過 go build xxxgo install xxx go get xxx等指令後,會將拉取的第三方xxx依賴包放在GOPATH/src目錄下,產生的二進位制可執行檔案放在 GOPATH/bin 目錄下,生成的中間快取檔案會被儲存在 GOPATH/pkg 下。

問題:GOPATH模式下沒有版本控制的概念,在執行 go get 的時候,獲取的永遠是最新的依賴包,下載到GOPATH/src,如果你有兩個工程依賴一個包的v1和v2版本,則會發生衝突,因為 GOPATH 模式下兩個工程內依賴的匯入路徑都是一樣的,因此兩個工程獲取的都是v2版本。

命令:顯然GOPATH模式下go get會將程式碼拉取到GOPATH/src,這個模式已經不推薦使用了。

govendor【不推薦使用】

在 Go 1.5版本之後,Go 提供了 GO15VENDOREXPERIMENT 環境變數(Go 1.6版本預設開啟該環境變數)和 Govendor 包管理工具,用於將 go build 時的應用路徑搜尋調整成為當前工程/vendor 目錄的方式,有效的解決了不同工程使用自己獨立的依賴包目錄。編譯 Go 程式碼會優先從vendor目錄先尋找依賴包,vendor目錄如果沒有找到,然後在 GOPATH 中查詢,都沒找到最後在 GOROOT 中查詢。

優勢:因為將第三方依賴完全和工程整合,使得專案構建速度快,且可以工作在無法連線外網的CI/CD流程中。

問題:放棄了依賴重用,使得冗餘度上升

下載:go install github.com/kardianos/govendor(govendor是第三方可執行檔案,下載可執行檔案用go install,用go get也行,但是會有告警)。

命令:govendor --help檢視所有命令(要先使用go get xxx將xxx依賴下載到$GOPATH/src中,此時go vendor包管理本質是基於GOPATH模式的)

命令 功能
govendor init 初始化vendor目錄
govendor add 新增包到vendor目錄(相關依賴則是從$GOPATH/src中獲取)
govendor add +external 新增所有外部包到vendor目錄
govendor get 拉取依賴包vendor目錄

然後我在govendor的程式碼庫中看到了下面這段話:?(這個README還是兩年前更新的,而且這個庫已經很久不維護了,嗯...)。

image-20220114180840455

go module

從Go1.11開始,官方推出Go module作為包管理工具,且從Go1.13開始為預設選擇啟用。GOMODULE模式下所有依賴的包存放在GOPATH/pkg/mod目錄下,所有第三方二進位制可執行檔案放在GOPATH/bin目錄下,且工程專案可以放在GOPATH路徑之外,但要求專案中需要有go.mod檔案(該檔案通過go mod init命令初始化可以得到)。

GOMODULE模式和GOPATH模式一樣都指定了依賴包存放的位置,而不是如vendor模式放入工程內,區別在於GOMODULE的go.mod檔案中記錄了所依賴包的具體版本,既實現了工程之間重用依賴包,且解決了GOPATH模式下不同工程無法依賴同一個包的不同版本的問題。

image-20220114191455736

啟用GOPATH模式要求工程目錄在GOPATH/src之下,而要使用GO MODULE模式,需要先開啟配置。在Go1.13之後,可以通過如下命令設定GO MODULE啟用狀態。

mac:(windows類似)

# 光開啟也是不行的,需要配合go.mod才能工作,下面講
export GO111MODULE=on
export GO111MODULE=off
#  當專案路徑在 $GOPATH 目錄外部時, 設定為 GO111MODULE = on 當專案路徑位於 GOPATH 內部時,即使存在 go.mod, 設定為 GO111MODULE = off
export GO111MODULE=auto

go mod命令:go help mod檢視相關幫助命令(govendor是第三方可執行檔案,但是go mod命令是go自帶的,不用額外go install)

命令 功能
go mod init 初始化當前資料夾,建立go.mod檔案,事實上,如果你的環境中GO111MODULE=on,使用類似goland的工具建立工程會自動生成go.mod
go mod tidy 包整理(多的刪去、少的拉取),使用之前自然是import了需要的庫了
go mod vendor 將依賴包複製到工程檔案的vendor目錄下

GO111MODULE=on且專案中包含go.mod檔案時,執行go get xxx 或 go install xxx下載的或者二進位制可執行檔案將放入GOPATH/pkg/mod目錄和GOPATH/bin目錄下。

go mod vendor:

這裡著重再提一下go mod vendor,剛剛還說govendor自己都不推薦用了,為什麼GOMODULE模式還提供了這個關聯go vendor功能的命令呢?

事實上,如果你需要使用vendor模式管理包,說明一定屬於如下兩種情況:

  1. 工作在GOPATH模式下,Go版本早於1.11或者GO111MODULE=off(因為這種方式依賴GOPATH模式,所以已經不推薦了)
  2. 工作在GO MODULE模式下,但是還是利用vendor管理依賴包,而go mod vendor就屬於這種情況(算是保留了vendor一線生機,畢竟還是有使用場景的,且go mod vendor利用GOMODULE模式為基礎,摒棄了GOPATH為基礎的govendor)。

結束語

碼字不易,三連才是真情~

剛建了個微信小群,歡迎加入一起嘮嗑,一同備戰秋招!

image-20220114200406881

image-20220110183620835

相關文章