備注:本猿翻譯水平有限,請各位看客見諒
翻譯內(nèi)容: go1.11 版本中 go help modules文檔內(nèi)容
總述
?模塊是Go Packages的關(guān)聯(lián)集合讲逛,是源代碼交換和版本控制的單元。
?Go命令直接支持使用模塊捻浦,包括記錄和解決對其他模塊的依賴隘膘。
?模塊取代了傳統(tǒng)的基于GOPATH的方法來指定在給定的構(gòu)建中使用哪個源文件刀森。
模塊的初級支持
?Go 1.11包含了對Go Module的初級支持逝薪,包括一個新的感知模塊命令“go get”隅要。我們打算繼續(xù)修正這一支持,并同時保持兼容性董济,直到它可以被宣布為正式版本(不再是初級版本)步清。在之后的版本,我們會移除對GOPATH和舊的“go get”命令的支持虏肾。獲得最新Go 1.11 Module技術(shù)支持的最快途徑是將你的代碼倉庫check out到GOPATH/src之外的一個目錄中廓啊,在那里創(chuàng)建一個go.mod文件(具體在下一節(jié)中描述),并在該文件根目錄中運行Go命令封豪。
?對于更細(xì)粒度的控制谴轮,Go支持包含一個臨時的環(huán)境變量GO111MODULE,它可以設(shè)置為三個字符串值之一:OFF吹埠、ON或AUTO(默認(rèn)值)书聚。
?如果GO111MODULE=OFF,則Go命令永遠(yuǎn)不會使用新的模塊功能支持藻雌。相反,它會在vendor目錄和GOPATH中查找依賴項斩个,即我們現(xiàn)在將其稱為“GOPATH模式”胯杭。
?如果GO111MODULE=ON,那么Go命令需要使用模塊受啥,而不能使用GOPATH模式做个。我們將其稱為“模塊感知模式”中的“模塊感知”命令鸽心。
?如果GO111MODULE=AUTO或未設(shè)置,則Go命令啟用或禁用取決于當(dāng)前目錄的對于模塊功能的支持居暖。
?只有項目代碼根目錄位于GOPATH/src同時本身包含go.mod文件顽频,或者位于包含go.mod文件的目錄下時,才能啟用模塊支持太闺。
?在模塊感知模式下糯景,GOPATH不再定義構(gòu)建期間導(dǎo)入的含義,但它仍然存儲下載的依賴項(在GOPATH/pkg/mod中)和已安裝的命令(在GOPATH/bin中省骂,除非設(shè)置了Gobin)蟀淮。
模塊的定義
?一個模塊由一個GO源代碼文件樹來定義,在該樹的根目錄中有一個go.mod文件钞澳。目錄包含一個go.mod文件被稱為模塊根(module root)怠惶。通常模塊根也將對應(yīng)于源代碼存儲庫根(但這通常不必要的)。模塊是模塊根及其子目錄中所有Go packages的集合轧粟,但不包括帶有自己的go.mod文件的子樹策治。
?“模塊路徑(module path)”是與模塊根對應(yīng)的導(dǎo)入路徑前綴。*.mod文件定義了模塊路徑兰吟,并通過給出模塊路徑和版本,再列出了在構(gòu)建期間解析導(dǎo)入時應(yīng)該使用的其他模塊的特定版本通惫。
?例如,go.mod聲明包含它的目錄是帶有路徑example.com/m的模塊的根目錄揽祥,它還聲明該模塊依賴于golang.org/x/text和gopkg.in/yaml.v 2的特定版本:
module example.com/m
require (
golang.org/x/text v0.3.0
gopkg.in/yaml.v2 v2.1.0
)
?mod文件還可以指定僅在直接構(gòu)建模塊時應(yīng)用的替換和排除版本讽膏;當(dāng)模塊被合并到更大的構(gòu)建中時,它們將被忽略拄丰。有關(guān)go.mod文件的更多信息府树,請參見“Go Help go.mod”。
?要啟動一個新模塊料按,只需在模塊目錄樹的根目錄中創(chuàng)建一個go.mod文件奄侠,只包含一個模塊語句≡乜螅“go mod init”命令可用于執(zhí)行以下操作:
go mod init example.com/m
?在已經(jīng)使用現(xiàn)有依賴項管理工具(如godep垄潮、glide或dep)的項目中,“Go mod init”還將添加與現(xiàn)有配置相匹配的Required語句闷盔。
?一旦go.mod文件存在弯洗,就不需要其他步驟了:Go命令,比如‘go build’逢勾、‘go test’牡整,甚至‘go list’都會根據(jù)需要自動添加新的依賴項來滿足導(dǎo)入。
主模塊和構(gòu)建列表
?“主模塊”是包含運行Go命令的目錄的模塊溺拱。Go命令通過查找當(dāng)前目錄中的go.mod逃贝,或者當(dāng)前目錄的父目錄茸时,或者父目錄的父目錄渣锦,以此類推來查找模塊根埃元。
?主模塊的go.mod文件通過請求织鲸、替換和排除語句定義了可供Go命令使用的軟件包的精確集合。依賴模塊(通過以下Required語句找到)也有助于定義這組包沪摄,
但只能通過它們的go.mod文件的Required語句來實現(xiàn):依賴模塊中的任何替換和排除語句都會被忽略躯嫉。因此,替換和排除語句允許主模塊完成對自己構(gòu)建的控制卓起,
而不受依賴項的完全控制和敬。
?為生成提供包的一組模塊稱為“構(gòu)建列表”。構(gòu)建列表最初只包含主模塊戏阅。然后昼弟,Go命令遞歸地將已經(jīng)在列表中的模塊所需的確切模塊版本添加到列表中,
直到列表中沒有任何可添加的內(nèi)容為止奕筐。如果某個特定模塊的多個版本被添加到列表中舱痘,那么在最后只保留最新版本(根據(jù)語義版本排序)以供在構(gòu)建中使用。
“GoList”命令提供關(guān)于主模塊和構(gòu)建列表的信息离赫。例如:
go list -m # print path of main module
go list -m -f={{.Dir}} # print root directory of main module
go list -m all # print build list
維護(hù)模塊Requirements
?mod文件意味著程序員和工具都可以閱讀和編輯芭逝。Go命令本身自動更新go.mod文件,以維護(hù)標(biāo)準(zhǔn)格式和Required語句的準(zhǔn)確性渊胸。
?任何找到不熟悉導(dǎo)入的go命令都會查找包含該導(dǎo)入的模塊旬盯,并自動將該模塊的最新版本添加到go.mod中。因此翎猛,在大多數(shù)情況下胖翰,將導(dǎo)入添加到源代碼并運行“go build”、“go test”或甚至“go List”就足夠了:作為分析包的一部分切厘,Go命令將發(fā)現(xiàn)并解析導(dǎo)入并更新go.mod文件萨咳。
?任何go命令都可以確定缺少模塊需求,并且必須添加疫稿,即使只考慮模塊中的單個包培他。另一方面,要確定模塊需求不再是必要的遗座,并且可以刪除舀凛,則需要全面查看模塊中的所有包,包括所有可能的構(gòu)建配置(體系結(jié)構(gòu)途蒋、操作系統(tǒng)猛遍、構(gòu)建標(biāo)記等)。“Go mod tidy”命令構(gòu)建該視圖螃壤,然后添加任何缺少的模塊需求并刪除不必要的需求。
?作為在go.mod中維護(hù)Required語句的一部分筋帖,Go命令跟蹤哪些提供由當(dāng)前模塊直接導(dǎo)入的包奸晴,哪些提供僅由其他模塊依賴項間接使用的包。僅用于間接使用的需求在go.mod文件中標(biāo)記為“// indirect”注釋日麸。間接需求一旦被其他直接需求暗示寄啼,就會自動從go.mod文件中刪除。只有在使用模塊時才會出現(xiàn)間接需求代箭,這些模塊不能聲明自己的一些依賴關(guān)系墩划,或者在模塊的依賴項顯式升級之前,才會出現(xiàn)它自己聲明的需求嗡综。
?由于這種自動維護(hù)乙帮,go.mod中的信息是最新的、可讀的構(gòu)建描述极景。
?“go get”命令更新go.mod以更改構(gòu)建中使用的模塊版本察净。一個模塊的升級可能意味著升級其他模塊,同樣地盼樟,一個模塊的降級可能意味著降低其他模塊的等級氢卡。“go get”命令也會進(jìn)行這些隱含的更改晨缴。如果go.mod是直接編輯的译秦,像‘Go Build’或‘Go List’這樣的命令將假定升級是有意的,并自動進(jìn)行任何隱含的升級击碗,并更新go.mod以反映它們筑悴。
?所需的"go mod"命令提供了在維護(hù)中使用的其他功能了解模塊和go.mod文件。請參見"go help mod".
?-mod 構(gòu)建標(biāo)識為更新和使用go.mod提供了額外的控制
?如果使用-mod=readonly調(diào)用延都,則上述go.mod的隱式自動更新不允許go命令雷猪。相反,當(dāng)需要對go.mod進(jìn)行任何更改時晰房,它就會失敗求摇。此設(shè)置對于檢查go.mod是否不需要更新非常有用。例如殊者,在持續(xù)集成和測試系統(tǒng)中与境。即使使用-mod=readonly,“go get”命令仍然允許更新go.mod猖吴,并且“go mod”命令不接受-mod標(biāo)志(或任何其他構(gòu)建標(biāo)志)摔刁。
?如果使用-mod=vendor調(diào)用,Go命令假定vendor目錄保存了依賴項的正確副本海蔽,并忽略了go.mod中的依賴項描述共屈。
?主模塊go.mod中排除語句不允許的模塊版本被認(rèn)為不可用绑谣,查詢不能返回。例如拗引,這些命令都是有效的:
go get github.com/gorilla/mux@latest # same (@latest is default for 'go get')
go get github.com/gorilla/mux@v1.6.2 # records v1.6.2
go get github.com/gorilla/mux@e3702bed2 # records v1.6.2
go get github.com/gorilla/mux@c856192 # records v0.0.0-20180517173623-c85619274f5d
go get github.com/gorilla/mux@master # records current meaning of master
模塊兼容性與語義版本化
?Go命令要求模塊使用語義版本借宵,并期望版本準(zhǔn)確地描述兼容性:它假定v1.5.4是v1.5.3、v1.4.0甚至v1.0.0的向后兼容替代品矾削。更普遍的情況是壤玫,Go命令期望包遵循“導(dǎo)入兼容性規(guī)則”,即:“如果舊包和新包具有相同的導(dǎo)入路徑哼凯,則新包必須向后兼容舊包欲间。”因為Go命令假定了導(dǎo)入兼容性規(guī)則断部,所以模塊定義只能設(shè)置其依賴項之一的最低要求版本:它不能設(shè)置最大版本或排除選定版本猎贴。盡管如此,導(dǎo)入兼容性規(guī)則并不是一個保證:可能是v1.5.4是錯誤的家坎,而不是版本1.5.3的向后兼容的替代嘱能。正因為如此,Go命令從不自動更新從舊版本到新版本的模塊虱疏。
?在語義版本控制中惹骂,更改主版本號表明與早期版本缺乏向后兼容性。為了保持導(dǎo)入兼容性做瞪,GO命令要求主版本v2或更高版本的模塊使用以該主版本作為最終元素的模塊路徑对粪。例如,example.com/m的版本v2.0.0必須使用模塊路徑example.com/m/v2装蓬,該模塊中的包將使用該路徑作為導(dǎo)入路徑前綴著拭,如example.com/m/v2/sub/pkg中所示。以這種方式包含模塊路徑中的主版本號和導(dǎo)入路徑稱為“語義導(dǎo)入版本控制”牍帚。主要版本v2的模塊的偽版本儡遮,而不是V0開始于主要版本,如v2.0.0-20180326061214-4fc5987536ef暗赶。作為特例鄙币,模塊路徑以gopkg.in/繼續(xù)使用在該系統(tǒng)上建立的約定:主版本總是存在的,它前面是一個點蹂随,而不是斜杠:gopkg.in/yaml.v1和gopkg.in/yaml.v2十嘿,而不是gopkg.in/yAML和gopkg.in/yAML/v2。
?GO命令將具有不同模塊路徑的模塊視為不相關(guān)的:它在example.com/m和example.com/m/v2之間沒有連接岳锁。具有不同主要版本的模塊可以在構(gòu)建中一起使用绩衷,并且由于它們的包使用不同的導(dǎo)入路徑這一事實而保持獨立。
?在語義版本控制中,主要版本V0用于初始開發(fā)咳燕,沒有對穩(wěn)定性或向后兼容性的期望勿决。主版本V0不會出現(xiàn)在模塊路徑中,因為這些版本正在為v1.0.0做準(zhǔn)備招盲,
而v1也沒有出現(xiàn)在模塊路徑中剥险。
?在引入語義導(dǎo)入版本控制約定之前編寫的代碼可以使用主要版本v2和更高版本來描述V0和v1中使用的同一組不版本化導(dǎo)入路徑。為了適應(yīng)這些代碼宪肖,如果源代碼存儲庫有一個沒有g(shù)o.mod的文件樹的v2.0.0或更高的標(biāo)記,則該版本被認(rèn)為是v1模塊可用版本的一部分健爬,并且在轉(zhuǎn)換為模塊版本時給出了一個不兼容的后綴控乾,如v2.0.0不兼容。不兼容標(biāo)簽也適用于從這些版本派生出來的偽版本娜遵,如v2.0.1-0.yyyymmddhmmss-abc defabc def不兼容蜕衡。
?通常,在V0版本设拟、預(yù)發(fā)布版本慨仿、偽版本或不兼容版本上的構(gòu)建列表(如“go list -m all”所報告的)中存在依賴關(guān)系,這表明升級依賴項時更有可能出現(xiàn)問題纳胧,因為對這些版本沒有預(yù)期的兼容性镰吆。
?有關(guān)語義導(dǎo)入版本控制的更多信息,請參見https://research.swtch.com/vgo-import跑慕;有關(guān)語義版本控制的更多信息万皿,請參見https://semver.org/。
模塊編碼設(shè)計
?有關(guān)信息核行,請參見https://research.swtch.com/vgo-module的信息關(guān)于版本控制系統(tǒng)中的源代碼如何映射到模塊文件樹牢硅。
模塊下載和驗證
?Go命令在主模塊的根目錄中與go.mod一起維護(hù)一個名為go.sum的文件,該文件包含特定模塊版本內(nèi)容的預(yù)期密碼校驗和芝雪。每次使用依賴項時减余,如果缺少該依賴項,則將其校驗和添加到go.sum中惩系,或者如果需要匹配go.sum中的現(xiàn)有條目位岔,則將其添加到go.sum。
?Go命令維護(hù)下載包的緩存蛆挫,并在下載時計算和記錄每個包的加密校驗和赃承。在正常操作中,go命令針對主模塊的go.sum文件檢查這些預(yù)先計算的校驗和悴侵,而不是在每次命令調(diào)用時重新計算它們瞧剖。“要驗證”命令檢查模塊下載的緩存副本是否仍然與其記錄的校驗和以及go.sum中的條目匹配。
?根據(jù)GOPROXY環(huán)境變量的設(shè)置抓于,GO命令可以從代理中獲取模塊做粤,而不是直接連接到源代碼控制系統(tǒng)。有關(guān)代理的詳細(xì)信息以及緩存下載的包的格式捉撮,請參見“go help goproxy”怕品。
模塊和vendoring
?在使用模塊時,Go命令完全忽略vendor目錄巾遭。
?默認(rèn)情況下肉康,Go命令通過從源代碼下載模塊并使用下載的副本來滿足依賴關(guān)系(在驗證之后,如上一節(jié)所述)灼舍。為了允許與較早版本的GO進(jìn)行互操作吼和,或者為了確保用于構(gòu)建的所有文件都存儲在一個文件樹中,“go mod vendor”在主模塊的根目錄中創(chuàng)建一個名為vendor的目錄骑素,并將所有依賴模塊中的包存儲在主模塊中支持包的生成和測試所需的依賴模塊中炫乓。
?若要使用主模塊的頂級vendor目錄進(jìn)行構(gòu)建以滿足依賴關(guān)系(禁用常用網(wǎng)絡(luò)源和本地緩存的使用),請使用“go build -mod=vendor”献丑。注意末捣,只使用主模塊的頂級vendor目錄;其他位置的vendor目錄仍然被忽略创橄。