<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Go語言重新開始,Go Modules的前世今生與基本使用

          共 6699字,需瀏覽 14分鐘

           ·

          2021-11-24 08:39



          2020年騰訊內(nèi)部的一份開發(fā)者報(bào)告顯示,Go語言已經(jīng)成為騰訊內(nèi)部第二大后端開發(fā)語言,在騰訊每天有大量的Go開發(fā)者在做業(yè)務(wù)和平臺(tái)開發(fā),大量的團(tuán)隊(duì)和項(xiàng)目使用也暴露出一些問題,隨著Go Modules的出現(xiàn),類似于內(nèi)部自簽發(fā)證書、安全審計(jì)等這些問題也逐漸得到解決。


          筆者在騰訊當(dāng)前負(fù)責(zé)騰訊云在Go編程語言使用上的一些問題,2021年初開始負(fù)責(zé)內(nèi)部goproxy服務(wù)并推廣Go Modules使用,這些技術(shù)支撐了騰訊云微信騰訊視頻騰訊游騰訊音樂騰訊會(huì)議等明星產(chǎn)品,并與公司內(nèi)部軟件源團(tuán)隊(duì)、工蜂團(tuán)隊(duì)、TRPC團(tuán)隊(duì)以及各個(gè)CI團(tuán)隊(duì)達(dá)成密切的合作。在本系列文章中,筆者就將由淺入深幫助大家開始學(xué)習(xí)和了解Go Modules


          一、Golang開發(fā)的模式演進(jìn)


          從Go出生開始,用戶就一直在使用GOPATH這個(gè)環(huán)境變量,隨著Go語言的快速發(fā)展和不斷壯大,由GOPATH引起的編譯依賴問題也開始逐漸出現(xiàn)。終于在2019年,Golang迎來10周年之際,Google Go團(tuán)隊(duì)終于開始把目光投向了這一伴隨了Golang十年的環(huán)境變量。



          二、GOPATH的使用


          目前在Go中存在兩種開發(fā)模式GOPATH mode和Go Modules mode。在Go Modules之前,Go開發(fā)中的依賴管理使用GOPATH開發(fā)模式。在GOPATH開發(fā)模式中,Go命令使用GOPATH環(huán)境變量來實(shí)現(xiàn)以下幾個(gè)功能:


          • go install命令安裝二進(jìn)制庫到$GOBIN,其默認(rèn)路徑為$GOPATH/bin。


          • go install命令安裝編譯好的包到$GOPATH/pkg/中,例如將example.com/y/z安裝到$GOPATH/pkg/example.com/y/z.a。


          • go get命令下載源碼包到$GOPATH/src/中,例如將example.com/y/z下載到$GOPATH/src/example。



          三、Go Modules的發(fā)展歷程


          GOPATH mode開發(fā)模式是終將要被淘汰的,Go官方在整個(gè)Go開發(fā)生態(tài)系統(tǒng)中添package version這一概念,進(jìn)而引入Go Modules開發(fā)模式。從GOPATH mode開發(fā)模式變換到Go Modules是一個(gè)漫長的過程,它已經(jīng)經(jīng)歷了數(shù)個(gè)Go的發(fā)行版本


          • Go 1.11 (2018年8月) 引入了GO111MODULE環(huán)境變量,其默認(rèn)值為auto。如果設(shè)置該變量 GO111MODULE=off,那么Go命令將始終使用GOPATH mode開發(fā)模式。如果設(shè)置該變量GO111MODULE=on,Go命令將始終使用Go Modules開發(fā)模式。如果設(shè)置該變量GO111MODULE=auto(或者不設(shè)置),Go命令行會(huì)根據(jù)當(dāng)前工作目錄來決定使用哪種模式,如果當(dāng)前目錄在$GOPATH/src以外,并且在根目錄下存在go.mod文件,那么Go命令會(huì)啟用Go Module模式,否則使用GOPATH開發(fā)模式。這個(gè)規(guī)則保證了所有在$GOPATH/src中使用auto值時(shí)原有編譯不受影響,并且還可以在其他目錄中來體驗(yàn)最新的Go Module開發(fā)模式。


          • Go 1.13 (2019年8月) 調(diào)整了GO111MODULE=auto模式中對$GOPATH/src的限制,如果一個(gè)代碼庫在$GOPATH/src中,并且有g(shù)o.mod文件的存在,Go命令會(huì)啟用Module開發(fā)模式。這允許用戶繼續(xù)在基于導(dǎo)入的層次結(jié)構(gòu)中組織他們的檢出代碼,但使用模塊進(jìn)行個(gè)別倉庫的導(dǎo)入。


          • Go 1.16 (2021年2月) 會(huì)將GO111MODULE=on做為默認(rèn)值,默認(rèn)啟用Go Module開發(fā)模式,也就是說,默認(rèn)情況下GOPATH開發(fā)模式將被徹底關(guān)閉。如果用戶需要使用GOPATH開發(fā)模式可以指定環(huán)境變量GO111MODULE=auto或者GO111MODULE=off。


          • Go 1.NN (???) 將會(huì)廢棄GO111MODULE環(huán)境變量和GOPATH開發(fā)模式,默認(rèn)完全使用Module開發(fā)模式。



          四、GOPATH與Go Modules的“相愛相殺”


          針對大家關(guān)心的幾個(gè)問題,筆者對此作出如下回答:


          (一)GOPATH變量會(huì)被移除嗎?


          不會(huì),GOPATH變量不會(huì)被移除。未來廢棄GOPATH開發(fā)模式并不是指刪除GOPATH環(huán)境變量,它會(huì)繼續(xù)保留,主要作用如下:


          • go install命令安裝二進(jìn)制到$GOBIN目錄,其默認(rèn)位置為$GOPATH/bin。


          • go get命令緩存下載的Modules到$GOMODCACHE目錄,默認(rèn)位置為$GOPATH/pkg/mod。


          • go get命令緩存下載的checksum數(shù)據(jù)到$GOPATH/pkg/sumdb目錄。



          (二)我可以繼續(xù)在`GOPATH/src/import/path`中創(chuàng)建代碼庫嗎?


          可以,很多開發(fā)者以這樣的文件結(jié)構(gòu)來組織自己的倉庫,你只需要在自己創(chuàng)建的倉庫中添加go.mod文件。



          (三)如果我想測試修改一個(gè)我需要的依賴庫,我該怎么做?


          如果你編譯自己的項(xiàng)目時(shí)依賴了一些未發(fā)布的變更,你可以使用go.mod的replace來實(shí)現(xiàn)你的需求。


          舉個(gè)例子,如果你已經(jīng)將golang.org/x/website和golang.org/x/tools下載到$GOPATH/src/目錄下,那么你可以在$GOPATH/src/golang.org/x/website/go.mod中添加下面的指令來完成替換:replace golang.org/x/tools=>$GOPATH/src/golang.org/x/tools


          當(dāng)然,replace指令是不感知GOPATH的,將代碼下載到其他目錄也一樣可以。



          五、從0開始使用Go Modules


          (一)創(chuàng)建一個(gè)新的Go Module


          首先創(chuàng)建一個(gè)新目錄/home/gopher/hello,然后進(jìn)入到這個(gè)目錄中,接著創(chuàng)建一個(gè)新文件,hello.go:


          package?hellofunc?Hello()?string?{????return?"Hello,?world."}


          然后再寫個(gè)對應(yīng)的測試文件hello_test.go:


          package?helloimport?"testing"func?TestHello(t?*testing.T)?{????want?:=?"Hello,?world."????if?got?:=?Hello();?got?!=?want?{????????t.Errorf("Hello()?=?%q,?want?%q",?got,?want)????}}


          現(xiàn)在我們擁有了一個(gè)package,但它還不是一個(gè)Module,因?yàn)檫€沒有創(chuàng)建go.mod文件。如果在/home/gopher/hello目錄中執(zhí)行g(shù)o test,則可以看到:$go test


          go:go.mod file not found in current directory or any parent directory;see'go help modules'


          可以看到Go命令行提示沒有找到go.mod文件,可以參考Go help Modules。這樣的話可以使用Go mod init來初始化一下,然后再執(zhí)行Go test:


          $?go?mod?init?example.com/hellogo:?creating?new?go.mod:?module?example.com/hellogo:?to?add?module?requirements?and?sums:go?mod?tidy$go?mod?tidygo?$?go?testPASSok?example.com/hello??0.020s$


          這樣的話,Module測試就完成了。然后執(zhí)行的go mod init命令創(chuàng)建了一個(gè)go.mod文件:


          $?cat?go.modmodule?example.com/hellogo 1.17



          (二)給Module添加依賴


          Go Modules的主要亮點(diǎn)在于在編程時(shí)使用別人寫的代碼,即引入一個(gè)依賴庫時(shí)能有非常好的體驗(yàn)。首先更新一下hello.go,引入rsc.io/quote來實(shí)現(xiàn)一些新的功能。


          package?helloimport?"rsc.io/quote"func?Hello()?string?{????return?quote.Hello()}


          然后,再測試一下:


          $?go?testhello.go:3:8:?no?required?module?provides?package?rsc.io/quote;?to?add?it:go?get?rsc.io/quote$?go?get?rsc.io/quotego:?downloading?rsc.io/quote?v1.5.2go:?downloading?rsc.io/sampler?v1.3.0go:?downloading?golang.org/x/text?v0.0.0-20170915032832-14c0d48ead0cgo:?added?golang.org/x/text?v0.0.0-20170915032832-14c0d48ead0cgo:?added?rsc.io/quote?v1.5.2go:?added?rsc.io/sampler?v1.3.0$?go?testPASSok example.com/hello  1.401s


          從Go 1.7開始,Go Modules開始使用lazyloading加載機(jī)制,依賴庫的更新需要根據(jù)提示手動(dòng)進(jìn)行相應(yīng)的更新。


          Go命令會(huì)根據(jù)go.mod的文件來解析拉取指定的依賴版本。如果在go.mod 中沒有找到指定的版本,會(huì)提示相應(yīng)的命令引導(dǎo)用戶添加,然后Go命令會(huì)去解析最新的穩(wěn)定版本(Latest),并且添加到go.mod文件中。在這個(gè)例子中可以看到,第一次執(zhí)行的Go test運(yùn)行需要rsc.io/quote這個(gè)依賴,但是在go.mod文件中并沒有找到,于是引導(dǎo)用戶去獲取latest版本,用戶通過go get rsc.io/quote獲取了最新版本v1.5.2,而且還另外下載了另外兩個(gè) rsc.io/quote需要的依賴:rsc.io/sampler和golang.org/x/text。間接依賴引用也會(huì)記錄在go.mod文件中,使用indirect注釋進(jìn)行標(biāo)記。


          $?cat?go.modmodule?example.com/hellogo?1.17require?(????golang.org/x/text?v0.0.0-20170915032832-14c0d48ead0c?//?indirect????rsc.io/quote?v1.5.2?//?indirect????rsc.io/sampler?v1.3.0?//?indirect)


          再一次運(yùn)行g(shù)o test命令不會(huì)重復(fù)上面的工作,因?yàn)間o.mod已經(jīng)是最新的,并且所需的依賴包已經(jīng)下載到本機(jī)中了(在$GOPATH/pkg/mod中):


          $?go?testPASSok example.com/hello  0.020s


          注意:雖然Go命令可以快速輕松地添加新的依賴項(xiàng),但并非沒有代價(jià)。


          如上面所提到,在項(xiàng)目中添加一個(gè)直接依賴可能會(huì)引入其他間接依賴。go list-m all命令可以列出當(dāng)前項(xiàng)目所依賴的所有依賴:


          $?go?list?-m?allexample.com/hellogolang.org/x/text?v0.0.0-20170915032832-14c0d48ead0crsc.io/quote?v1.5.2rsc.io/sampler v1.3.0


          在go list的輸出結(jié)果中,可以看到當(dāng)前的Module,也被稱為main module會(huì)展示在第一行,然后其他的會(huì)按照Module path進(jìn)行排序。其中依賴golang.org/x/text的版本號(hào)v0.0.0-20170915032832-14c0d48ead0c是一個(gè)偽版本號(hào),它是Go版本的一種,指向了一個(gè)沒有打tag的commit上。


          另外除了go.mod文件,go命令還維護(hù)了一個(gè)叫做go.sum的文件,這個(gè)文件包含了每個(gè)版本對應(yīng)的加密哈希值。


          $?cat?go.sumgolang.org/x/text?v0.0.0-20170915032832-14c0d48ead0c?h1:qgOY6WgZO...golang.org/x/text?v0.0.0-20170915032832-14c0d48ead0c/go.mod?h1:Nq...rsc.io/quote?v1.5.2?h1:w5fcysjrx7yqtD/aO+QwRjYZOKnaM9Uh2b40tElTs3...rsc.io/quote?v1.5.2/go.mod?h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPX...rsc.io/sampler?v1.3.0?h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/Q...rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9...


          Go命令使用go.sum來保證每次下載的依賴庫代碼和第一次都是一致的,進(jìn)而來保證項(xiàng)目不會(huì)出現(xiàn)一些異常情況,所以go.mod和go.sum都應(yīng)該上傳到git等版本控制系統(tǒng)中。



          (三)更新依賴


          從上面go list-m all命令的輸出中,可以看到在庫golang.org/x/text中使用了一個(gè)偽版本號(hào)。首先把這個(gè)版本好更新到最新的穩(wěn)定版本:


          $?go?get?golang.org/x/textgo:?downloading?golang.org/x/text?v0.3.7go:?upgraded?golang.org/x/text?v0.0.0-20170915032832-14c0d48ead0c?=>?v0.3.7$?go?testPASSok example.com/hello  0.013s


          測試仍然可以通過,然后再執(zhí)行一次go list-m all:


          $?go?list?-m?allexample.com/hellogolang.org/x/text?v0.3.7rsc.io/quote?v1.5.2rsc.io/sampler?v1.3.0$?cat?go.modmodule?example.com/hellogo?1.17require?(????golang.org/x/text?v0.3.7?//?indirect????rsc.io/quote?v1.5.2?//?indirect????rsc.io/sampler?v1.3.0?//?indirect)



          六、結(jié)語


          Go通過Go Modules的依賴管理統(tǒng)一了Go生態(tài)中眾多的第三方的依賴管理,并且高度集成在Go命令行中,無需開發(fā)者們額外安裝使用,目前在當(dāng)前維護(hù)的Go版本中都已經(jīng)支持了Go Modules。還沒有切換到Go Modules的用戶,強(qiáng)烈建議大家開始使用它,這無論是從團(tuán)隊(duì)開發(fā)體驗(yàn)、性能還是安全等方面,都能提供諸多的優(yōu)質(zhì)特性和保障。



          留言互動(dòng),好禮放送


          在留言區(qū)寫下本文讀后感,并將本推文不設(shè)分組分享到朋友圈點(diǎn)亮「點(diǎn)贊」和「在看」,截止到11月29日上午10點(diǎn),留言區(qū)評論點(diǎn)贊數(shù)第一名憑朋友圈截圖和留言截圖私聊騰小云(微信號(hào):txcloudsq)可獲得視頻禮盒1個(gè)↓↓


          (視頻禮盒)


          快來留言區(qū)寫下本文讀后感吧,分享你學(xué)習(xí)Go Modules技術(shù)的收獲與切身感悟~



          ?推薦閱讀


          千萬并發(fā)連接下,如何保障網(wǎng)絡(luò)性能?

          從0到1:輕松搞定從RPC到服務(wù)化框架的設(shè)計(jì)!

          是什么讓AIoT開發(fā)更便捷?—TencentOS

          超專業(yè)解析!10分鐘帶你搞懂Linux中直接I/O原理






          ??騰訊云加社區(qū)精品內(nèi)容欄目《云薦大咖》,特邀行業(yè)佼者,聚焦在前沿技術(shù)的落地與理論實(shí)踐之上,持續(xù)為您解讀云時(shí)代熱點(diǎn)技術(shù),探秘行業(yè)發(fā)展新機(jī)。「閱讀原文」一鍵訂閱《云薦大咖》專欄,看云端技術(shù)起落,聽大咖指點(diǎn)迷津!

          瀏覽 92
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  亚洲AV无码国产综合专区 | 黄色视频久久久 | 国产一级做a爰片久久 | 成人免费A片 | 免费视频在线观看a |