您好,登錄后才能下訂單哦!
如何學(xué)會使用 go modules,針對這個問題,這篇文章詳細(xì)介紹了相對應(yīng)的分析和解答,希望可以幫助更多想解決這個問題的小伙伴找到更簡單易行的方法。
導(dǎo)讀:go modules
是 golang 1.11 新加的特性。如今 1.13 都已經(jīng)發(fā)布了第 7 個小版本了,幾乎所有大項(xiàng)目均已開始使用,這自然也包括 Kubernetes 生態(tài)中的眾多項(xiàng)目。筆者在開發(fā) OAM 相關(guān)項(xiàng)目的時候,卻發(fā)現(xiàn) modules 的各項(xiàng)功能看似簡單,卻并沒有那么好用,于是便想給大家分享一下使用心得。
簡單說就是包管理,Golang 的包管理素來以混亂著稱,以前是依賴 $GOPATH
,只要你的代碼放在指定路徑下就好了,完全沒有“包管理”的概念。被社區(qū)吐槽了很久以后開始搞 vendor
機(jī)制,簡單來說就是代碼不光是可以放到指定路徑,還可以放在項(xiàng)目自身路徑的 vendor 文件夾。這個解決的問題是:你引用的代碼包上游變更不會直接影響你的項(xiàng)目,這顯然是開始關(guān)心“包版本”了。遺憾的是依舊沒有解決包管理的問題,比如不同的包依賴了同一個包的不同版本怎么辦?版本間代碼沖突怎么辦?vendor
機(jī)制并沒有解決,于是圍繞 vendor/
社區(qū)就出了幾十個包管理工具,一時間百花齊放、百家爭鳴、各有所長,導(dǎo)致 golang 的包管理生態(tài)變得有些混亂。對這段歷史感興趣的可以閱讀下筆者曾經(jīng)寫的文章《Go 包管理的前世今生》。
更有意思的是,在 go 官方社區(qū)看到包管理工具的亂象后,也做了個功能類似的工具 dep
,原理與其他各類依靠vendor/
機(jī)制的包管理工具類似,準(zhǔn)備對包管理做統(tǒng)一。當(dāng)大家對 dep
工具報以期望并紛紛開始切換到 dep
工具管理依賴包的時候,go 官方又發(fā)布了現(xiàn)在的 modules 機(jī)制,完全放棄了之前的 dep
工具與 vendor
機(jī)制。這樣的操作在社區(qū)引起了巨大的爭議,modules 與 go get
、go build
等官方工具生態(tài)有很好的集成,官方的意圖自然是希望拋開原有的歷史包袱,通過全新的方式拯救世界。然而實(shí)際體驗(yàn)下來,卻依舊不盡如人意。
總的來說大趨勢已經(jīng)是用 modules
,go1.13 也對 modules 機(jī)制做了不少工作。
言歸正傳,本文的目標(biāo)是希望能用 5~10 分鐘時間帶您學(xué)會使用 go modules,然后通過 QA 的形式,描述一些常見的問題。如果希望詳細(xì)理解相關(guān)內(nèi)容,也可以參考官方文檔。
modules 機(jī)制在 go 里面的子命令是 go mod
。
modules 機(jī)制是 go 1.11 才引入的,所以開始用之前先檢查下自己的 go 版本 go version
,建議使用最新的 1.13 版本,涵蓋了 module 機(jī)制相關(guān)的較多更新和功能。
在保證 go 版本至少在 1.11 或以上之后,就要開啟一下環(huán)境變量 GO111MODULE,啟用 module 機(jī)制。
export GO111MODULE=on
或者設(shè)置為 auto 模式,這樣在 GOPATH 路徑下的項(xiàng)目可以不使用 module 機(jī)制。
export GO111MODULE=auto
建議加到 ~/.bashrc
、~/.zshrc
等配置中啟動便自動生效。
如果您的項(xiàng)目之前已經(jīng)用 modules 管理了,那么到此為止你本地的環(huán)境已經(jīng)完成初始化了。
如果項(xiàng)目里之前沒有使用 modules,切換過來也很簡單,刪除原先的 vendor
文件夾(保險起見可以移動到項(xiàng)目之外的地方),在項(xiàng)目里執(zhí)行一下初始化命令即可。
go mod init [module名稱]
包名跟以前一樣,還是跟 go path 強(qiáng)關(guān)聯(lián)的,比如我們的項(xiàng)目一般是在 http://github.com/oam-dev/oam-go-sdk
,那么你的包名就是這個了。
go mod init github.com/oam-dev/oam-go-sdk
初始化完成后就會看見項(xiàng)目里有個 go.mod
文件。
然后通過 go mod download
就可以下載所有原先 vendor
中的依賴。
<a name="2eee5f31"></a>
使用了 go module
以后,你的許多命令就會與包管理集成,比如 go get
、go build
、go run
都會自動查找并在go.mod
里面更新依賴。
所以按照 Go 官方團(tuán)隊(duì)的意思,一般情況下,你根本不用關(guān)心包管理的問題了。( 當(dāng)然,這真的純粹只是官方在 YY )
所以到這里你就已經(jīng)學(xué)會 go modules
了,沒超過5分鐘吧?
實(shí)際因?yàn)?go 官方對包管理重視的太晚,各種包都沒有版本的概念,隨隨便便就會出現(xiàn)各種沖突,而且由于 go modules 實(shí)在是太自動了,所以就算你學(xué)會了怎么用 modules,最后還是會比較頭疼。
下面我們就以 FAQ 的形式回答項(xiàng)目中遇到各種問題怎么辦。
Go module 加入了代理的機(jī)制,只要設(shè)置一個代理地址,就可以提供代理訪問。阿里云就提供了這樣一個 go 的代理 ,是完全免費(fèi)的服務(wù)。公共代理倉庫會代理并緩存go模塊,你可以利用該代理來避免 DNS 污染或其他問題導(dǎo)致的模塊拉取緩慢或失敗的問題,加速你的項(xiàng)目構(gòu)建。
設(shè)置的方式非常簡單,只需要設(shè)置如下環(huán)境變量即可,執(zhí)行命令:
export GOPROXY=https://mirrors.aliyun.com/goproxy/
go1.13 加入了 mirror 機(jī)制,可以通過 go env -w
設(shè)置 mirror,其實(shí)就是之前的 GOPROXY 做的更到位一些,執(zhí)行命令:
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/,direct
逗號后面可以增加多個 proxy,最后的 direct 則是在所有 proxy 都找不到的時候,直接訪問,代理訪問不到的私有倉庫就可以正常使用了。
這個功能基本上是在家遠(yuǎn)程辦公的必備工具了。
這個幾乎是最常見的問題,比較簡單的解決方案是 hack 一下 git 配置:
git config --global url."git@gitlab.your-company.com:<your>/<package>.git".insteadOf "https://gitlab.your-company.com/<your>/<package>.git"
這個方案依賴你本地的 ~/.ssh/id_rsa
, 這樣你就可以正常 go get
了。
方案一:上述方式通過修改 git config
,卻依賴你本地的 ~/.ssh/id_rsa
,在構(gòu)建時可以通過 multistage-build 把私鑰 add 到 stage 0
里面 build,然后用后面新的 stage 生成鏡像,這樣構(gòu)建的鏡像就不會包含私鑰;
方案二: 更為安全的方式是,在每次構(gòu)建 Docker 鏡像之前,先在本地用 go mod vendor
把包緩存下來,在 Dockerfile 構(gòu)建鏡像過程中還是用 GOPATH 和 Vendor 機(jī)制來管理依賴。。
先查看版本:
$ go list -m -versions rsc.io/sampler rsc.io/sampler v1.0.0 v1.2.0 v1.2.1 v1.3.0 v1.3.1 v1.99.99
再更新:
$ go get rsc.io/sampler@v1.3.1 go: finding rsc.io/sampler v1.3.1 go: downloading rsc.io/sampler v1.3.1 go: extracting rsc.io/sampler v1.3.1 $ go test PASS ok example.com/hello 0.022s
go 的依賴與項(xiàng)目名直接相關(guān),這就導(dǎo)致如果我們使用了 github 上的項(xiàng)目,然后項(xiàng)目的維護(hù)人員突發(fā)奇想改個項(xiàng)目名稱,就會導(dǎo)致所有依賴它的項(xiàng)目都無法找到依賴。
還好有 replace 的機(jī)制:
replace golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a => github.com/golang/crypto v0.0.0-20190313024323-a1f597ede03a
這就要梳理版本了,是最沒有捷徑的。一個比較簡單的辦法是把所有 go.mod
里不需要指定版本的包全部刪掉,僅指定必要的包版本,然后通過 go build
讓項(xiàng)目自動構(gòu)建依賴包的版本。
通過 go mod graph 可以查看具體依賴路徑:
$ go mod graph github.com/oam-dev/oam-go-sdk github.com/go-logr/logr@v0.1.0 github.com/oam-dev/oam-go-sdk github.com/onsi/ginkgo@v1.10.1 github.com/oam-dev/oam-go-sdk github.com/onsi/gomega@v1.7.0 github.com/oam-dev/oam-go-sdk github.com/stretchr/testify@v1.4.0 github.com/oam-dev/oam-go-sdk golang.org/x/net@v0.0.0-20191004110552-13f9640d40b9 github.com/oam-dev/oam-go-sdk k8s.io/api@v0.17.0 github.com/oam-dev/oam-go-sdk k8s.io/apimachinery@v0.17.0 github.com/oam-dev/oam-go-sdk k8s.io/client-go@v0.17.0 github.com/oam-dev/oam-go-sdk sigs.k8s.io/controller-runtime@v0.4.0 ...
左邊是項(xiàng)目包,右邊是被依賴的包和版本。
如果確實(shí)存在兩個需要指定版本的包互相沖突,那就要做取舍,修改代碼,升級或降級某個包了。
如果在代碼調(diào)試過程中,涉及到修改其他依賴項(xiàng)目代碼,這時候就要引用本地包,也可以采用 replace 機(jī)制:
require ( golang.org/x/crypto v0.0.0 ) replace golang.org/x/crypto v0.0.0 => ../crypto
后面這個就是個相對項(xiàng)目路徑的本地依賴所在路徑。
解決了上面的這些問題,基本上你就可以愉快的使用 module 功能啦。
go mod 里還有一些其他功能,也在此列舉,方便大家查閱:
OAM(Open Application Model)開放應(yīng)用模型是阿里聯(lián)合微軟針對云原生應(yīng)用的模型,第一次對“以應(yīng)用為中心”的基礎(chǔ)設(shè)施和構(gòu)建規(guī)范進(jìn)行了完整的闡述。應(yīng)用管理者只要遵守這個規(guī)范,就可以編寫出一個自包含、自描述的“應(yīng)用定義文件”。
OAM 將應(yīng)用劃分為應(yīng)用組件和應(yīng)用特征兩部分,應(yīng)用組件是應(yīng)用本身的邏輯,而應(yīng)用特征則是云上的各種通用能力(如擴(kuò)縮容、監(jiān)控、灰度等等),大大提升了應(yīng)用構(gòu)建時模塊化復(fù)用能力,將云上的各類資源和能力都轉(zhuǎn)化為了標(biāo)準(zhǔn)化的可“聲明”對象。
同時 OAM 強(qiáng)調(diào)關(guān)注點(diǎn)分離,通過標(biāo)準(zhǔn)化的模型將應(yīng)用開發(fā)不同階段的 API 進(jìn)行分層,流程上先由研發(fā)定義應(yīng)用組件,再由運(yùn)維配置云上的各種策略,最后由基礎(chǔ)設(shè)施團(tuán)隊(duì)統(tǒng)一提供各類模塊化的能力。OAM 則在其中起著彼此協(xié)作的粘合劑作用,大大提高了應(yīng)用交付的效率。
O
關(guān)于如何學(xué)會使用 go modules問題的解答就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,如果你還有很多疑惑沒有解開,可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。