hc@ubt:~$ go get github.com/hyper-carrot/go_lib/logging
命令go get可以根據(jù)要求和實(shí)際情況從互聯(lián)網(wǎng)上下載或更新指定的代碼包及其依賴(lài)包,并對(duì)它們進(jìn)行編譯和安裝。在上面這個(gè)示例中,我們從著名的代碼托管站點(diǎn)Github上下載了一個(gè)項(xiàng)目(或稱(chēng)代碼包),并安裝到了環(huán)境變量GOPATH中包含的第一個(gè)工作區(qū)中。與此同時(shí),我們也知道了這個(gè)代碼包的導(dǎo)入路徑就是github.com/hyper-carrot/go_lib/logging。
一般情況下,為了分離自己與第三方的代碼,我們會(huì)設(shè)置兩個(gè)或更多的工作區(qū)。我們現(xiàn)在有一個(gè)目錄路徑為/home/hc/golang/lib的工作區(qū),并且它是環(huán)境變量GOPATH值中的第一個(gè)目錄路徑。注意,環(huán)境變量GOPATH中包含的路徑不能與環(huán)境變量GOROOT的值重復(fù)。好了,如果我們使用go get命令下載和安裝代碼包,那么這些代碼包都會(huì)被安裝在上面這個(gè)工作區(qū)中。我們暫且把這個(gè)工作區(qū)叫做Lib工作區(qū)。在我們運(yùn)行go get github.com/hyper-carrot/go_lib/logging之后,這個(gè)代碼包就應(yīng)該會(huì)被保存在Lib工作的src目錄下,并且已經(jīng)被安裝妥當(dāng),如下所示:
/home/hc/golang/lib:
bin/
pkg/
linux_386/
github.com/
hyper-carrot/
go_lib/
logging.a
src/
github.com/
hyper-carrot/
go_lib/
logging/
...
另一方面,如果我們想把一個(gè)項(xiàng)目上傳到Github網(wǎng)站(或其他代碼托管網(wǎng)站)上并被其他人使用的話,那么我們就應(yīng)該把這個(gè)項(xiàng)目當(dāng)做一個(gè)代碼包來(lái)看待。其實(shí)我們?cè)谥耙呀?jīng)提到過(guò)原因,go get命令會(huì)將項(xiàng)目下的所有子目錄和源碼文件存放到第一個(gè)工作區(qū)的src目錄下,而src目錄下的所有子目錄都會(huì)是某個(gè)代碼包導(dǎo)入路徑的一部分或者全部。也就是說(shuō),我們應(yīng)該直接在項(xiàng)目目錄下存放子代碼包和源碼文件,并且直接存放在項(xiàng)目目錄下的源碼文件所聲明的包名應(yīng)該與該項(xiàng)目名相同(除非它是命令源碼文件)。這樣做可以讓其他人使用go get命令從Github站點(diǎn)上下載你的項(xiàng)目之后直接就能使用它。
實(shí)際上,像goc2p項(xiàng)目這樣直接以項(xiàng)目根目錄的路徑作為工作區(qū)路徑的做法是不被推薦的。之所以這樣做主要是想讓讀者更容易的理解Go語(yǔ)言的工程結(jié)構(gòu)和工作區(qū)概念,也可以讓讀者看到另一種項(xiàng)目結(jié)構(gòu)。當(dāng)然,如果你的項(xiàng)目使用了gb這樣的工具那就是另外一回事了。這樣的項(xiàng)目的根目錄就應(yīng)該被視為一個(gè)工作區(qū)(但是你不必把它加入到GOPATH環(huán)境變量中)。它應(yīng)該由git clone下載到Go語(yǔ)言工作區(qū)之外的某處,而不是使用go get命令。
遠(yuǎn)程導(dǎo)入路徑分析
實(shí)際上,go get命令所做的動(dòng)作也被叫做代碼包遠(yuǎn)程導(dǎo)入,而傳遞給該命令的作為代碼包導(dǎo)入路徑的那個(gè)參數(shù)又被叫做代碼包遠(yuǎn)程導(dǎo)入路徑。
go get命令不僅可以從像Github這樣著名的代碼托管站點(diǎn)上下載代碼包,還可以從任何命令支持的代碼版本控制系統(tǒng)(英文為Version Control System,簡(jiǎn)稱(chēng)為VCS)檢出代碼包。任何代碼托管站點(diǎn)都是通過(guò)某個(gè)或某些代碼版本控制系統(tǒng)來(lái)提供代碼上傳下載服務(wù)的。所以,更嚴(yán)格地講,go get命令所做的是從代碼版本控制系統(tǒng)的遠(yuǎn)程倉(cāng)庫(kù)中檢出/更新代碼包并對(duì)其進(jìn)行編譯和安裝。
該命令所支持的VCS的信息如下表:
表0-2 go get命令支持的VCS
| 名稱(chēng) | 主命令 | 說(shuō)明 |
|---|---|---|
| Mercurial | hg | Mercurial是一種輕量級(jí)分布式版本控制系統(tǒng),采用Python語(yǔ)言實(shí)現(xiàn),易于學(xué)習(xí)和使用,擴(kuò)展性強(qiáng)。 |
| Git | git | Git最開(kāi)始是Linux Torvalds為了幫助管理 Linux 內(nèi)核開(kāi)發(fā)而開(kāi)發(fā)的一個(gè)開(kāi)源的分布式版本控制軟件。但現(xiàn)在已被廣泛使用。它是被用來(lái)進(jìn)行有效、高速的各種規(guī)模項(xiàng)目的版本管理。 |
| Subversion | svn | Subversion是一個(gè)版本控制系統(tǒng),也是第一個(gè)將分支概念和功能納入到版本控制模型的系統(tǒng)。但相對(duì)于Git和Mercurial而言,它只算是傳統(tǒng)版本控制系統(tǒng)的一員。 |
| Bazaar | bzr | Bazaar是一個(gè)開(kāi)源的分布式版本控制系統(tǒng)。但相比而言,用它來(lái)作為VCS的項(xiàng)目并不多。 |
go get命令在檢出代碼包之前必須要知道代碼包遠(yuǎn)程導(dǎo)入路徑所對(duì)應(yīng)的版本控制系統(tǒng)和遠(yuǎn)程倉(cāng)庫(kù)的URL。
如果該代碼包在本地工作區(qū)中已經(jīng)存在,則會(huì)直接通過(guò)分析其路徑來(lái)確定這幾項(xiàng)信息。go get命令支持的幾個(gè)版本控制系統(tǒng)都有一個(gè)共同點(diǎn),那就是會(huì)在檢出的項(xiàng)目目錄中存放一個(gè)元數(shù)據(jù)目錄,名稱(chēng)為“.”前綴加其主命令名。例如,Git會(huì)在檢出的項(xiàng)目目錄中加入一個(gè)名為“.git”的子目錄。所以,這樣就很容易判定代碼包所用的版本控制系統(tǒng)。另外,又由于代碼包已經(jīng)存在,我們只需通過(guò)代碼版本控制系統(tǒng)的更新命令來(lái)更新代碼包,因此也就不需要知道其遠(yuǎn)程倉(cāng)庫(kù)的URL了。對(duì)于已存在于本地工作區(qū)的代碼包,除非要求強(qiáng)行更新代碼包,否則go get命令不會(huì)進(jìn)行重復(fù)下載。如果想要強(qiáng)行更新代碼包,可以在執(zhí)行go get命令時(shí)加入-u標(biāo)記。這一標(biāo)記會(huì)稍后介紹。
如果本地工作區(qū)中不存在該代碼包,那么就只能通過(guò)對(duì)代碼包遠(yuǎn)程導(dǎo)入路徑進(jìn)行分析來(lái)獲取相關(guān)信息了。首先,go get命令會(huì)對(duì)代碼包遠(yuǎn)程導(dǎo)入路徑進(jìn)行靜態(tài)分析。為了使分析過(guò)程更加方便快捷,go get命令程序中已經(jīng)預(yù)置了幾個(gè)著名代碼托管網(wǎng)站的信息。如下表:
表0-3 預(yù)置的代碼托管站點(diǎn)的信息
| 名稱(chēng) | 主域名 | 支持的VCS | 代碼包遠(yuǎn)程導(dǎo)入路徑示例 |
|---|---|---|---|
| Bitbucket | bitbucket.org | Git, Mercurial | bitbucket.org/user/project bitbucket.org/user/project/sub/directory |
| GitHub | github.com | Git | github.com/user/project github.com/user/project/sub/directory |
| Google Code Project Hosting | code.google.com | Git, Mercurial, Subversion | code.google.com/p/project code.google.com/p/project/sub/directory code.google.com/p/project.subrepository code.google.com/p/project.subrepository/sub/directory |
| Launchpad | launchpad.net | Bazaar | launchpad.net/project launchpad.net/project/series launchpad.net/project/series/sub/directory launchpad.net/~user/project/branch launchpad.net/~user/project/branch/sub/directory |
| IBM DevOps Services | hub.jazz.net | Git | hub.jazz.net/git/user/project hub.jazz.net/git/user/project/sub/directory |
一般情況下,代碼包遠(yuǎn)程導(dǎo)入路徑中的第一個(gè)元素就是代碼托管網(wǎng)站的主域名。在靜態(tài)分析的時(shí)候,go get命令會(huì)將代碼包遠(yuǎn)程導(dǎo)入路徑與預(yù)置的代碼托管站點(diǎn)的主域名進(jìn)行匹配。如果匹配成功,則在對(duì)代碼包遠(yuǎn)程導(dǎo)入路徑的初步檢查后返回正常的返回值或錯(cuò)誤信息。如果匹配不成功,則會(huì)再對(duì)代碼包遠(yuǎn)程導(dǎo)入路徑進(jìn)行動(dòng)態(tài)分析。至于動(dòng)態(tài)分析的過(guò)程,我就不在這里詳細(xì)展開(kāi)了。
如果對(duì)代碼包遠(yuǎn)程導(dǎo)入路徑的靜態(tài)分析或/和動(dòng)態(tài)分析成功并獲取到對(duì)應(yīng)的版本控制系統(tǒng)和遠(yuǎn)程倉(cāng)庫(kù)URL,那么go get命令就會(huì)進(jìn)行代碼包檢出或更新的操作。隨后,go get命令會(huì)在必要時(shí)以同樣的方式檢出或更新這個(gè)代碼包的所有依賴(lài)包。
自定義代碼包遠(yuǎn)程導(dǎo)入路徑
如果你想把你編寫(xiě)的(被托管在不同的代碼托管網(wǎng)站上的)代碼包的遠(yuǎn)程導(dǎo)入路徑統(tǒng)一起來(lái),或者不希望讓你的代碼包中夾雜某個(gè)代碼托管網(wǎng)站的域名,那么你可以選擇自定義你的代碼包遠(yuǎn)程導(dǎo)入路徑。這種自定義的實(shí)現(xiàn)手段叫做“導(dǎo)入注釋”。導(dǎo)入注釋的寫(xiě)法示例如下:
package analyzer // import "hypermind.cn/talon/analyzer"
代碼包analyzer實(shí)際上屬于我的一個(gè)網(wǎng)絡(luò)爬蟲(chóng)項(xiàng)目。這個(gè)項(xiàng)目的代碼被托管在了Github網(wǎng)站上。它的網(wǎng)址是:https://github.com/hyper-carrot/talon。如果用標(biāo)準(zhǔn)的導(dǎo)入路徑來(lái)下載analyzer代碼包的話,命令應(yīng)該這樣寫(xiě)go get github.com/hyper-carrot/talon/analyzer。不過(guò),如果我們像上面的示例那樣在該代碼包中的一個(gè)源碼文件中加入導(dǎo)入注釋的話,這樣下載它就行不通了。我們來(lái)看一看這個(gè)導(dǎo)入注釋。
導(dǎo)入注釋的寫(xiě)法如同一條代碼包導(dǎo)入語(yǔ)句。不同的是,它出現(xiàn)在了單行注釋符//的右邊,因此Go語(yǔ)言編譯器會(huì)忽略掉它。另外,它必須出現(xiàn)在源碼文件的第一行語(yǔ)句(也就是代碼包聲明語(yǔ)句)的右邊。只有符合上述這兩個(gè)位置條件的導(dǎo)入注釋才是有效的。再來(lái)看其中的引號(hào)部分。被雙引號(hào)包裹的應(yīng)該是一個(gè)符合導(dǎo)入路徑語(yǔ)法規(guī)則的字符串。其中,hypermind.cn是我自己的一個(gè)域名。實(shí)際上,這也是用來(lái)替換掉我想隱去的代碼托管網(wǎng)站域名及部分路徑(這里是github.com/hyper-carrot)的那部分。在hypermind.cn右邊的依次是我的項(xiàng)目的名稱(chēng)以及要下載的那個(gè)代碼包的相對(duì)路徑。這些與其標(biāo)準(zhǔn)導(dǎo)入路徑中的內(nèi)容都是一致的。為了清晰起見(jiàn),我們?cè)賮?lái)做下對(duì)比。
github.com/hyper-carrot/talon/analyzer // 標(biāo)準(zhǔn)的導(dǎo)入路徑
hypermind.cn /talon/analyzer // 導(dǎo)入注釋中的導(dǎo)入路徑
你想用你自己的域名替換掉標(biāo)準(zhǔn)導(dǎo)入路徑中的哪部分由你自己說(shuō)了算。不過(guò)一般情況下,被替換的部分包括代碼托管網(wǎng)站的域名以及你在那里的用戶(hù)ID就可以了。這足以達(dá)到我們最開(kāi)始說(shuō)的那兩個(gè)目的。
雖然我們?cè)趖alon項(xiàng)目中的所有代碼包中都加入了類(lèi)似的導(dǎo)入注釋?zhuān)俏覀円廊粺o(wú)法通過(guò)go get hypermind.cn/talon/analyzer命令來(lái)下載這個(gè)代碼包。因?yàn)橛蛎?code>hypermind.cn所指向的網(wǎng)站并沒(méi)有加入相應(yīng)的處理邏輯。具體的實(shí)現(xiàn)步驟應(yīng)該是這樣的:
編寫(xiě)一個(gè)可處理HTTP請(qǐng)求的程序。這里無(wú)所謂用什么編程語(yǔ)言去實(shí)現(xiàn)。當(dāng)然,我推薦你用Go語(yǔ)言去做。
將這個(gè)處理程序與hypermind.cn/talon這個(gè)路徑關(guān)聯(lián)在一起,并總是在作為響應(yīng)的HTML文檔的頭中寫(xiě)入下面這行內(nèi)容:
<meta name="go-import" content="hypermind.cn/talon git https://github.com/hyper-carrot/talon">
hypermind.cn/talon/analyzer熟悉HTML的讀者都應(yīng)該知道,這行內(nèi)容會(huì)被視為HTML文檔的元數(shù)據(jù)。它實(shí)際上go get命令的文檔中要求的寫(xiě)法。它的模式是這樣的:
<meta name="go-import" content="import-prefix vcs repo-root">
實(shí)際上,content屬性中的import-prefix的位置上應(yīng)該填入我們自定義的遠(yuǎn)程代碼包導(dǎo)入路徑的前綴。這個(gè)前綴應(yīng)該與我們的處理程序關(guān)聯(lián)的那個(gè)路徑相一致。而vsc顯然應(yīng)該代表與版本控制系統(tǒng)有關(guān)的標(biāo)識(shí)。還記得表0-2中的主命令列嗎?這里的填入內(nèi)容就應(yīng)該該列中的某一項(xiàng)。在這里,由于talon項(xiàng)目使用的是Git,所以這里應(yīng)該填入git。至于repo-root,它應(yīng)該是與該處理程序關(guān)聯(lián)的路徑對(duì)應(yīng)的Github網(wǎng)站的URL。在這里,這個(gè)路徑是hypermind.cn/talon,那么這個(gè)URL就應(yīng)該是https://github.com/hyper-carrot/talon。后者也是talon項(xiàng)目的實(shí)際網(wǎng)址。
好了,在我們做好上述處理程序之后,go get hypermind.cn/talon/analyzer命令的執(zhí)行結(jié)果就會(huì)是正確的。analyzer代碼包及其依賴(lài)包中的代碼會(huì)被下載到GOPATH環(huán)境變量中的第一個(gè)工作區(qū)目錄的src子目錄中,然后被編譯并安裝。
注意,具體的代碼包源碼存放路徑會(huì)是/home/hc/golang/lib/src/hypermind.cn/talon/analyzer。也就是說(shuō),存放路徑(包括代碼包源碼文件以及相應(yīng)的歸檔文件的存放路徑)會(huì)遵循導(dǎo)入注釋中的路徑(這里是hypermind.cn/talon/analyzer),而不是原始的導(dǎo)入路徑(這里是github.com/hyper-carrot/talon/analyzer)。另外,我們只需在talon項(xiàng)目的每個(gè)代碼包中的某一個(gè)源碼文件中加入導(dǎo)入注釋?zhuān)@些導(dǎo)入注釋中的路徑都必須是一致的。在這之后,我們就只能使用hypermind.cn/talon/作為talon項(xiàng)目中的代碼包的導(dǎo)入路徑前綴了。一個(gè)反例如下:
hc@ubt:~$ go get github.com/hyper-carrot/talon/analyzer
package github.com/hyper-carrot/talon/analyzer: code in directory /home/hc/golang/lib/src/github.com/hyper-carrot/talon/analyzer expects import "hypermind.cn/talon/analyzer"
與自定義的代碼包遠(yuǎn)程導(dǎo)入路徑有關(guān)的內(nèi)容我們就介紹到這里。從中我們也可以看出,Go語(yǔ)言為了讓使用者的項(xiàng)目與代碼托管網(wǎng)站隔離所作出的努力。只要你有自己的網(wǎng)站和一個(gè)不錯(cuò)的域名,這就很容易搞定并且非常值得。這會(huì)在你的代碼包的使用者面前強(qiáng)化你的品牌,而不是某個(gè)代碼托管網(wǎng)站的。當(dāng)然,使你的代碼包導(dǎo)入路徑整齊劃一是最直接的好處。
OK,言歸正傳,我下面繼續(xù)關(guān)注go get這個(gè)命令本身。
命令特有標(biāo)記
go get命令可以接受所有可用于go build命令和go install命令的標(biāo)記。這是因?yàn)?code>go get命令的內(nèi)部步驟中完全包含了編譯和安裝這兩個(gè)動(dòng)作。另外,go get命令還有一些特有的標(biāo)記,如下表所示:
表0-4 go get命令的特有標(biāo)記說(shuō)明
| 標(biāo)記名稱(chēng) | 標(biāo)記描述 |
|---|---|
| -d | 讓命令程序只執(zhí)行下載動(dòng)作,而不執(zhí)行安裝動(dòng)作。 |
| -f | 僅在使用-u標(biāo)記時(shí)才有效。該標(biāo)記會(huì)讓命令程序忽略掉對(duì)已下載代碼包的導(dǎo)入路徑的檢查。如果下載并安裝的代碼包所屬的項(xiàng)目是你從別人那里Fork過(guò)來(lái)的,那么這樣做就尤為重要了。 |
| -fix | 讓命令程序在下載代碼包后先執(zhí)行修正動(dòng)作,而后再進(jìn)行編譯和安裝。 |
| -insecure | 允許命令程序使用非安全的scheme(如HTTP)去下載指定的代碼包。如果你用的代碼倉(cāng)庫(kù)(如公司內(nèi)部的Gitlab)沒(méi)有HTTPS支持,可以添加此標(biāo)記。請(qǐng)?jiān)诖_定安全的情況下使用它。 |
| -t | 讓命令程序同時(shí)下載并安裝指定的代碼包中的測(cè)試源碼文件中依賴(lài)的代碼包。 |
| -u | 讓命令利用網(wǎng)絡(luò)來(lái)更新已有代碼包及其依賴(lài)包。默認(rèn)情況下,該命令只會(huì)從網(wǎng)絡(luò)上下載本地不存在的代碼包,而不會(huì)更新已有的代碼包。 |
為了更好的理解這幾個(gè)特有標(biāo)記,我們先清除Lib工作區(qū)的src目錄和pkg目錄中的所有子目錄和文件?,F(xiàn)在我們使用帶有-d標(biāo)記的go get命令來(lái)下載同樣的代碼包:
hc@ubt:~$ go get -d github.com/hyper-carrot/go_lib/logging
現(xiàn)在,讓我們?cè)賮?lái)看一下Lib工作區(qū)的目錄結(jié)構(gòu):
/home/hc/golang/lib:
bin/
pkg/
src/
github.com/
hyper-carrot/
go_lib/
logging/
...
我們可以看到,go get命令只將代碼包下載到了Lib工作區(qū)的src目錄,而沒(méi)有進(jìn)行后續(xù)的編譯和安裝動(dòng)作。這個(gè)加入-d標(biāo)記的結(jié)果。
再來(lái)看-fix標(biāo)記。我們知道,絕大多數(shù)計(jì)算機(jī)編程語(yǔ)言在進(jìn)行升級(jí)和演進(jìn)過(guò)程中,不可能保證100%的向后兼容(Backward Compatibility)。在計(jì)算機(jī)世界中,向后兼容是指在一個(gè)程序或者代碼庫(kù)在更新到較新的版本后,用舊的版本程序創(chuàng)建的軟件和系統(tǒng)仍能被正常操作或使用,或在舊版本的代碼庫(kù)的基礎(chǔ)上編寫(xiě)的程序仍能正常編譯運(yùn)行的能力。Go語(yǔ)言的開(kāi)發(fā)者們已想到了這點(diǎn),并提供了官方的代碼升級(jí)工具——fix。fix工具可以修復(fù)因Go語(yǔ)言規(guī)范變更而造成的語(yǔ)法級(jí)別的錯(cuò)誤。關(guān)于fix工具,我們將放在本節(jié)的稍后位置予以說(shuō)明。
假設(shè)我們本機(jī)安裝的Go語(yǔ)言版本是1.5,但我們的程序需要用到一個(gè)很早之前用Go語(yǔ)言的0.9版本開(kāi)發(fā)的代碼包。那么我們?cè)谑褂?code>go get命令的時(shí)候可以加入-fix標(biāo)記。這個(gè)標(biāo)記的作用是在檢出代碼包之后,先對(duì)該代碼包中不符合Go語(yǔ)言1.5版本的語(yǔ)言規(guī)范的語(yǔ)法進(jìn)行修正,然后再下載它的依賴(lài)包,最后再對(duì)它們進(jìn)行編譯和安裝。
標(biāo)記-u的意圖和執(zhí)行的動(dòng)作都比較簡(jiǎn)單。我們?cè)趫?zhí)行go get命令時(shí)加入-u標(biāo)記就意味著,如果在本地工作區(qū)中已存在相關(guān)的代碼包,那么就是用對(duì)應(yīng)的代碼版本控制系統(tǒng)的更新命令更新它,并進(jìn)行編譯和安裝。這相當(dāng)于強(qiáng)行更新指定的代碼包及其依賴(lài)包。我們來(lái)看如下示例:
hc@ubt:~$ go get -v github.com/hyper-carrot/go_lib/logging
因?yàn)槲覀冊(cè)谥耙呀?jīng)檢出并安裝了這個(gè)代碼包,所以我們執(zhí)行上面這條命令后什么也沒(méi)發(fā)生。還記得加入標(biāo)記-v標(biāo)記意味著會(huì)打印出被構(gòu)建的代碼包的名字嗎?現(xiàn)在我們使用標(biāo)記-u來(lái)強(qiáng)行更新代碼包:
hc@ubt:~$ go get -v -u github.com/hyper-carrot/go_lib/logging
github.com/hyper-carrot/go_lib (download)
其中,“(download)”后綴意味著命令從遠(yuǎn)程倉(cāng)庫(kù)檢出或更新了該行顯示的代碼包。如果我們要查看附帶-u的go get命令到底做了些什么,還可以加上一個(gè)-x標(biāo)記,以打印出用到的命令。讀者可以自己試用一下它。
智能的下載
命令go get還有一個(gè)很值得稱(chēng)道的功能。在使用它檢出或更新代碼包之后,它會(huì)尋找與本地已安裝Go語(yǔ)言的版本號(hào)相對(duì)應(yīng)的標(biāo)簽(tag)或分支(branch)。比如,本機(jī)安裝Go語(yǔ)言的版本是1.x,那么go get命令會(huì)在該代碼包的遠(yuǎn)程倉(cāng)庫(kù)中尋找名為“go1”的標(biāo)簽或者分支。如果找到指定的標(biāo)簽或者分支,則將本地代碼包的版本切換到此標(biāo)簽或者分支。如果沒(méi)有找到指定的標(biāo)簽或者分支,則將本地代碼包的版本切換到主干的最新版本。
前面我們說(shuō)在執(zhí)行go get命令時(shí)也可以加入-x標(biāo)記,這樣可以看到go get命令執(zhí)行過(guò)程中所使用的所有命令。不知道讀者是否已經(jīng)自己嘗試了。下面我們還是以代碼包github.com/hyper-carrot/go_lib為例,并且通過(guò)之前示例中的命令的執(zhí)行此代碼包已經(jīng)被檢出到本地。這時(shí)我們?cè)俅胃逻@個(gè)代碼包:
hc@ubt:~$ go get -v -u -x github.com/hyper-carrot/go_lib
github.com/hyper-carrot/go_lib (download)
cd /home/hc/golang/lib/src/github.com/hyper-carrot/go_lib
git fetch
cd /home/hc/golang/lib/src/github.com/hyper-carrot/go_lib
git show-ref
cd /home/hc/golang/lib/src/github.com/hyper-carrot/go_lib
git checkout origin/master
WORK=/tmp/go-build034263530
在上述示例中,go get命令通過(guò)git fetch命令將所有遠(yuǎn)程分支更新到本地,而后有用git show-ref命令列出本地和遠(yuǎn)程倉(cāng)庫(kù)中記錄的代碼包的所有分支和標(biāo)簽。最后,當(dāng)確定沒(méi)有名為“go1”的標(biāo)簽或者分支后,go get命令使用git checkout origin/master命令將代碼包的版本切換到主干的最新版本。下面,我們?cè)诒镜卦黾右粋€(gè)名為“go1”的標(biāo)簽,看看go get命令的執(zhí)行過(guò)程又會(huì)發(fā)生什么改變:
hc@ubt:~$ cd ~/golang/lib/src/github.com/hyper-carrot/go_lib
hc@ubt:~/golang/lib/src/github.com/hyper-carrot/go_lib$ git tag go1
hc@ubt:~$ go get -v -u -x github.com/hyper-carrot/go_lib
github.com/hyper-carrot/go_lib (download)
cd /home/hc/golang/lib/src/github.com/hyper-carrot/go_lib
git fetch
cd /home/hc/golang/lib/src/github.com/hyper-carrot/go_lib
git show-ref
cd /home/hc/golang/lib/src/github.com/hyper-carrot/go_lib
git show-ref tags/go1 origin/go1
cd /home/hc/golang/lib/src/github.com/hyper-carrot/go_lib
git checkout tags/go1
WORK=/tmp/go-build636338114
將這兩個(gè)示例進(jìn)行對(duì)比,我們會(huì)很容易發(fā)現(xiàn)它們之間的區(qū)別。第二個(gè)示例的命令執(zhí)行過(guò)程中使用git show-ref查看所有分支和標(biāo)簽,當(dāng)發(fā)現(xiàn)有匹配的信息又通過(guò)git show-ref tags/go1 origin/go1命令進(jìn)行精確查找,在確認(rèn)無(wú)誤后將本地代碼包的版本切換到標(biāo)簽“go1”之上。
命令go get的這一功能是非常有用的。我們的代碼在直接或間接依賴(lài)某些同時(shí)針對(duì)多個(gè)Go語(yǔ)言版本開(kāi)發(fā)的代碼包時(shí),可以自動(dòng)的檢出其正確的版本。也可以說(shuō),go get命令內(nèi)置了一定的代碼包多版本依賴(lài)管理的功能。
到這里,我向大家介紹了go get命令的使用方式。go get命令與之前介紹的兩個(gè)命令一樣,是我們編寫(xiě)Go語(yǔ)言程序、構(gòu)建Go語(yǔ)言項(xiàng)目時(shí)必不可少的輔助工具。