Go語言版本控制及包依賴管理

傳統(tǒng)Go構(gòu)建以及包依賴管理

image.png
  • 我們知道go get獲取的代碼會(huì)放在GOROOT/src下面纵柿,而go build會(huì)在GOROOT/src和GOPATH/src下面按照import path去搜索package昂儒,由于go get 獲取的都是各個(gè)package repo的trunk/mainline的代碼委可,因此,Go 1.5之前的Go compiler都是基于目標(biāo)Go程序依賴包的trunk/mainline代碼去編譯的拾酝。這樣的機(jī)制帶來的問題是顯而易見的卡者,至少包括:
  1. 因依賴包的trunk的變化崇决,導(dǎo)致不同人獲取和編譯你的包/程序時(shí)得到的結(jié)果實(shí)質(zhì)是不同的底挫,即不能實(shí)現(xiàn)reproduceable build
  2. 因依賴包的trunk的變化脸侥,引入不兼容的實(shí)現(xiàn),導(dǎo)致你的包/程序無法通過編譯
  3. 因依賴包演進(jìn)而無法通過編譯官边,導(dǎo)致你的包/程序無法通過編譯
  • 為了實(shí)現(xiàn)reporduceable build外遇,Go 1.5引入了Vendor機(jī)制臀规,Go編譯器會(huì)優(yōu)先在vendor下搜索依賴的第三方包,這樣如果開發(fā)者將特定版本的依賴包存放在vendor下面并提交到code repo玩徊,那么所有人理論上都會(huì)得到同樣的編譯結(jié)果谨究,從而實(shí)現(xiàn)reporduceable build

Go語言版本控制

  • 在沒有版本控制時(shí),go get 的一個(gè)重大缺陷是對(duì)于給定的更新無法知道是否是用戶所期望的畔塔。

  • Go 將在下個(gè)版本(1.11)中看到官方的包版本控制鸯屿,去除了 GOPATH 依賴寄摆,同時(shí)還引入了 module(模塊) 的概念。

  • 版本控制可以讓我們能夠?qū)崿F(xiàn)重編譯桑阶。當(dāng)我讓你試用我程序最新版本時(shí)勾邦,我清楚的知道你不僅僅獲取到的是我最新程序的代碼,還包括我代碼所依賴的相同版本的包萎河,這樣才能編譯出完全一樣的二進(jìn)制包。

  • 版本控制還能讓我們不同階段保持同樣的編譯方式换可,即使我們的依賴包可能有新版本了厦幅,只要我們的配置未允許使用,go 命令也不會(huì)使用新版本的包译荞。

  • 盡管添加版本控制是必須的功能吞歼,但同時(shí)也不能失去go 命令行現(xiàn)有的優(yōu)秀特性:簡(jiǎn)單塔猾、高效、易懂糯俗,所以它應(yīng)該足夠透明不能破壞掉go get 本身功能睦擂。

  • Go新版本中保留了go get的精華部分顿仇,增加了重復(fù)構(gòu)建,采用了語義化的版本控制鸿吆,棄用了 vendor,廢棄了基礎(chǔ)工程創(chuàng)建時(shí)依賴GOPATH述呐,并且提供了老項(xiàng)目平滑遷移的方式伞剑。

Go添加版本控制共分四個(gè)步驟

導(dǎo)入兼容規(guī)則

  • 包管理系統(tǒng)中最大的痛苦在于解決兼容性問題

    比如,大多數(shù)系統(tǒng)中包B 聲明需要的包D 版本是6或者更高版本市埋,然后包C聲明所需的包D 版本是2,3和4,但不能高于版本5恕刘。如果你正在編寫包A 缤谎,你想同時(shí)引入包B 和C ,那么你不走運(yùn)了:沒有一個(gè)獨(dú)立的D 版本可以供B 和C 同時(shí)選擇編譯進(jìn)A褐着。B 和C 做的都是合理的坷澡,你也沒辦法改變它,所以你就被卡住了含蓉。

  • 為了避免主導(dǎo)者設(shè)計(jì)一個(gè)導(dǎo)致現(xiàn)有的大型程序無法編譯的系統(tǒng)项郊,提案要求包作者遵循以下導(dǎo)入兼容性原則:

    如果一個(gè)舊包和新包有相同的導(dǎo)入路徑,新包必須向后兼容舊包 這條規(guī)則是對(duì)前面 Go FAQ 的重申斟赚,引用 FAQ 中最后講的:“如果需要完全變更着降,那么就創(chuàng)建個(gè)新導(dǎo)入路徑的包”。開發(fā)者希望能通過語義化的版本來表達(dá)這樣一個(gè)變更拗军,因此我們把語義化版本控制也加入到我們提案中任洞。具體點(diǎn)說,主版本2 和更新的版本可以通過在路徑中包含版本信息來區(qū)分发侵,比如:


import "github.com/go-yaml/yaml/v2"

  • 包作者遵循導(dǎo)入兼容性原則可以讓我們減少適配工作交掏,讓系統(tǒng)更簡(jiǎn)單的同時(shí)也讓包生態(tài)減少碎片化
    當(dāng)然,實(shí)際上盡管作者盡最大努力去做了刃鳄,更新時(shí)也難免會(huì)出現(xiàn)破壞用戶使用的情況盅弛。因此,使用一個(gè)不頻繁升級(jí)的升級(jí)機(jī)制很重要叔锐,這也是接下來我們要講的挪鹏。

最小版本規(guī)則

  • 幾乎現(xiàn)在所有的包管理包括dep和cargo都在構(gòu)建時(shí)使用最新的包版本,基于兩方面的重要因素掌腰,被認(rèn)為這是個(gè)錯(cuò)誤的約定:

    首先狰住,“最新可用版本”有可能因?yàn)橥獠渴录?dǎo)致變更,像新版本發(fā)布齿梁。也許今晚你依賴的包中有人會(huì)發(fā)布個(gè)新版本催植,第二天早上你再編譯有可能就產(chǎn)生不同的結(jié)果了;

    第二勺择,為了覆蓋這個(gè)默認(rèn)約定创南,開發(fā)者花費(fèi)大量的時(shí)間告訴包管理器不使用哪個(gè)版本的包。

  • 提案中我們使用了不同的方式省核,稱之為最小版本選擇稿辙。

    構(gòu)建時(shí)每個(gè)包默認(rèn)使用的是最老的可用版本,這個(gè)方式讓昨天和今天的編譯不會(huì)有變化气忠,因?yàn)槟憧偛粫?huì)在今天發(fā)布一個(gè)更老版本吧邻储。更好的是,開發(fā)者只需告訴包管理器最小可用的那個(gè)版本旧噪,包管理器就可以很快的決定哪個(gè)版本可用吨娜。我們稱它為最小版本選擇一方面是因?yàn)槲覀冞x擇的是最小版本,另一方面是因?yàn)閷?duì)整個(gè)系統(tǒng)來說是最小化的淘钟,避免了現(xiàn)有系統(tǒng)的復(fù)雜性宦赠。

    最小版本選擇為模塊指定了其依賴模塊的最低版本需求,這為后續(xù)升級(jí)和降級(jí)操作提供了一個(gè)很好的選擇。同時(shí)勾扭,它還可以通過排除指定版本的依賴或者指定特殊版本依賴完成編譯毡琉。

    最小版本選擇在不鎖定文件情況下默認(rèn)就完成了可重復(fù)構(gòu)建。

    最小版本選擇是導(dǎo)入兼容的關(guān)鍵妙色。用戶不會(huì)再說:“不桅滋,版本太新了”,更多情況是面臨“不燎斩,版本太舊了”虱歪,這種情況下解決方案很明確:升級(jí)新版本就可以了。

Go Module

  • Go Module是共享一個(gè)導(dǎo)入路徑前綴的包集合栅表,也就是我們所說的模塊路徑

    Module是版本控制的單元笋鄙,Module的版本通過語義化的版本字符串表示,當(dāng)開發(fā)中使用Git 時(shí)怪瓶,開發(fā)者通過給模塊的Git 資源庫添加一個(gè)新tag的方式來定義一個(gè)新的語義化版本萧落。盡管強(qiáng)烈推薦使用語義化版本的方式,但也支持指向特定commit洗贰。

  • 模塊定義在一個(gè)叫g(shù)o.mod的新文件里找岖,里面包含了模塊所依賴包的最小版本

    下面就是個(gè)簡(jiǎn)單的go.mod文件:


module "rsc.io/hello"

require (

"golang.org/x/text" v0.0.0-20180208041248-4e4a3210bb54

"rsc.io/quote" v1.5.2

)

這個(gè)文件通過路徑標(biāo)識(shí) rsc.io/hello 定義了一個(gè)模塊,它本身還依賴于兩個(gè)其他模塊:golang.org/x/text 和 rsc.io/quote 敛滋,這個(gè)模塊自身編譯的時(shí)候使用的是 go.mod 文件中指定的依賴列表的版本许布。對(duì)于更上一層的編譯,其他導(dǎo)入這個(gè)模塊的地方將使用它較新的版本編譯绎晃。

包發(fā)布者最好使用語義化的 tag 發(fā)布版本蜜唾,vgo 也鼓勵(lì)通過打tag的版本號(hào)方式,而不是任意的提交版本庶艾。

  • 除了指定必須的依賴版本袁余,go.mod 文件還可以實(shí)現(xiàn)前面章節(jié)中提到的排除和替換的版本,但是這些只有當(dāng)直接編譯該模塊的時(shí)候起作用咱揍,在模塊作為整體工程一部分編譯時(shí)就不行了

  • Goinstall 和舊的 go get 通過像git 和hg 這樣的版本控制工具直接下載代碼颖榜,這種方式存在很多問題,其中包括碎片化嚴(yán)重:用戶如果沒有bzr 就沒法下載托管在Bazaar 資源庫的代碼煤裙。相比之下掩完,Go Module則是通過HTTP 下載zip 包的方式。

  • Module統(tǒng)一通過zip包的形式提供可以讓下載協(xié)議更簡(jiǎn)單硼砰,公司或者個(gè)人可以處于任何原因考慮(安全或者想要緩存副本防止源被刪除)自己做下載代理藤为,使用代理來確保可用性并且通過go.mod定義了哪些代碼需要用到

Go 命令

  • go 命令必須更新才能使用模塊功能夺刑。一個(gè)重要的變化就是常用的構(gòu)建命令,像 gobuild, go install, go run, 和 go test 將需要按指定需求解析對(duì)應(yīng)的依賴關(guān)系了

  • 最重要的變化還是終結(jié)了GOPATH作為Go 代碼工作空間的設(shè)置,由于go.mod文件包含了完整的模塊路徑并且還定義了每個(gè)使用的依賴的版本遍愿,因此包含go.mod文件的目錄就可以被認(rèn)為是一個(gè)目錄樹的根目錄了存淫,該目錄樹作用于自身的工作空間,并且和其他類似的目錄彼此隔離≌犹睿現(xiàn)在你只需git clone然后cd就可以直接擼代碼了桅咆,不再需要GOPATH了

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市坞笙,隨后出現(xiàn)的幾起案子岩饼,更是在濱河造成了極大的恐慌,老刑警劉巖薛夜,帶你破解...
    沈念sama閱讀 211,194評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件籍茧,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡梯澜,警方通過查閱死者的電腦和手機(jī)寞冯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來晚伙,“玉大人吮龄,你說我怎么就攤上這事∨亓疲” “怎么了漓帚?”我有些...
    開封第一講書人閱讀 156,780評(píng)論 0 346
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)午磁。 經(jīng)常有香客問我尝抖,道長(zhǎng),這世上最難降的妖魔是什么漓踢? 我笑而不...
    開封第一講書人閱讀 56,388評(píng)論 1 283
  • 正文 為了忘掉前任牵署,我火速辦了婚禮,結(jié)果婚禮上喧半,老公的妹妹穿的比我還像新娘奴迅。我一直安慰自己,他們只是感情好挺据,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,430評(píng)論 5 384
  • 文/花漫 我一把揭開白布取具。 她就那樣靜靜地躺著倍权,像睡著了一般敏释。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上深寥,一...
    開封第一講書人閱讀 49,764評(píng)論 1 290
  • 那天婉称,我揣著相機(jī)與錄音块仆,去河邊找鬼构蹬。 笑死,一個(gè)胖子當(dāng)著我的面吹牛悔据,可吹牛的內(nèi)容都是我干的庄敛。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼科汗,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼藻烤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起头滔,我...
    開封第一講書人閱讀 37,679評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤怖亭,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后坤检,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體兴猩,經(jīng)...
    沈念sama閱讀 44,122評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,459評(píng)論 2 325
  • 正文 我和宋清朗相戀三年缀蹄,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了峭跳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,605評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡缺前,死狀恐怖蛀醉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情衅码,我是刑警寧澤拯刁,帶...
    沈念sama閱讀 34,270評(píng)論 4 329
  • 正文 年R本政府宣布,位于F島的核電站逝段,受9級(jí)特大地震影響垛玻,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜奶躯,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,867評(píng)論 3 312
  • 文/蒙蒙 一帚桩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嘹黔,春花似錦账嚎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至喂江,卻和暖如春召锈,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背获询。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評(píng)論 1 265
  • 我被黑心中介騙來泰國(guó)打工涨岁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留拐袜,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,297評(píng)論 2 360
  • 正文 我出身青樓梢薪,卻偏偏與公主長(zhǎng)得像阻肿,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子沮尿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,472評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容