您好,登錄后才能下訂單哦!
今天小編給大家分享一下go get命令的作用是什么的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
“go get”命令可以借助代碼管理工具通過遠程拉取或更新代碼包及其依賴包,并自動完成編譯和安裝。“go get”命令可以動態獲取遠程代碼包,在使用“go get”命令前,需要安裝與遠程包匹配的代碼管理工具,如Git、SVN、HG等,參數中需要提供一個包名。
go get 命令可以借助代碼管理工具通過遠程拉取或更新代碼包及其依賴包,并自動完成編譯和安裝。整個過程就像安裝一個 App 一樣簡單。
這個命令可以動態獲取遠程代碼包,目前支持的有 BitBucket、GitHub、Google Code 和 Launchpad。在使用 go get 命令前,需要安裝與遠程包匹配的代碼管理工具,如 Git、SVN、HG 等,參數中需要提供一個包名。
這個命令在內部實際上分成了兩步操作:第一步是下載源碼包,第二步是執行 go install。
go get命令——一鍵獲取代碼、編譯并安裝
hc@ubt:~$ go get github.com/hyper-carrot/go_lib/logging
命令go get
可以根據要求和實際情況從互聯網上下載或更新指定的代碼包及其依賴包,并對它們進行編譯和安裝。在上面這個示例中,我們從著名的代碼托管站點Github上下載了一個項目(或稱代碼包),并安裝到了環境變量GOPATH中包含的第一個工作區中。與此同時,我們也知道了這個代碼包的導入路徑就是github.com/hyper-carrot/go_lib/logging。
一般情況下,為了分離自己與第三方的代碼,我們會設置兩個或更多的工作區。我們現在有一個目錄路徑為/home/hc/golang/lib的工作區,并且它是環境變量GOPATH值中的第一個目錄路徑。注意,環境變量GOPATH中包含的路徑不能與環境變量GOROOT的值重復。好了,如果我們使用go get
命令下載和安裝代碼包,那么這些代碼包都會被安裝在上面這個工作區中。我們暫且把這個工作區叫做Lib工作區。在我們運行go get github.com/hyper-carrot/go_lib/logging
之后,這個代碼包就應該會被保存在Lib工作的src目錄下,并且已經被安裝妥當,如下所示:
/home/hc/golang/lib:
bin/
pkg/
linux_386/
github.com/
hyper-carrot/
go_lib/
logging.a
src/
github.com/
hyper-carrot/
go_lib/
logging/
...
另一方面,如果我們想把一個項目上傳到Github網站(或其他代碼托管網站)上并被其他人使用的話,那么我們就應該把這個項目當做一個代碼包來看待。其實我們在之前已經提到過原因,go get
命令會將項目下的所有子目錄和源碼文件存放到第一個工作區的src目錄下,而src目錄下的所有子目錄都會是某個代碼包導入路徑的一部分或者全部。也就是說,我們應該直接在項目目錄下存放子代碼包和源碼文件,并且直接存放在項目目錄下的源碼文件所聲明的包名應該與該項目名相同(除非它是命令源碼文件)。這樣做可以讓其他人使用go get
命令從Github站點上下載你的項目之后直接就能使用它。
實際上,像goc2p項目這樣直接以項目根目錄的路徑作為工作區路徑的做法是不被推薦的。之所以這樣做主要是想讓讀者更容易的理解Go語言的工程結構和工作區概念,也可以讓讀者看到另一種項目結構。當然,如果你的項目使用了gb這樣的工具那就是另外一回事了。這樣的項目的根目錄就應該被視為一個工作區(但是你不必把它加入到GOPATH環境變量中)。它應該由git clone
下載到Go語言工作區之外的某處,而不是使用go get
命令。
遠程導入路徑分析
實際上,go get
命令所做的動作也被叫做代碼包遠程導入,而傳遞給該命令的作為代碼包導入路徑的那個參數又被叫做代碼包遠程導入路徑。
go get
命令不僅可以從像Github這樣著名的代碼托管站點上下載代碼包,還可以從任何命令支持的代碼版本控制系統(英文為Version Control System,簡稱為VCS)檢出代碼包。任何代碼托管站點都是通過某個或某些代碼版本控制系統來提供代碼上傳下載服務的。所以,更嚴格地講,go get
命令所做的是從代碼版本控制系統的遠程倉庫中檢出/更新代碼包并對其進行編譯和安裝。
該命令所支持的VCS的信息如下表:
表0-2 go get
命令支持的VCS
名稱 | 主命令 | 說明 |
---|---|---|
Mercurial | hg | Mercurial是一種輕量級分布式版本控制系統,采用Python語言實現,易于學習和使用,擴展性強。 |
Git | git | Git最開始是Linux Torvalds為了幫助管理 Linux 內核開發而開發的一個開源的分布式版本控制軟件。但現在已被廣泛使用。它是被用來進行有效、高速的各種規模項目的版本管理。 |
Subversion | svn | Subversion是一個版本控制系統,也是第一個將分支概念和功能納入到版本控制模型的系統。但相對于Git和Mercurial而言,它只算是傳統版本控制系統的一員。 |
Bazaar | bzr | Bazaar是一個開源的分布式版本控制系統。但相比而言,用它來作為VCS的項目并不多。 |
go get
命令在檢出代碼包之前必須要知道代碼包遠程導入路徑所對應的版本控制系統和遠程倉庫的URL。
如果該代碼包在本地工作區中已經存在,則會直接通過分析其路徑來確定這幾項信息。go get
命令支持的幾個版本控制系統都有一個共同點,那就是會在檢出的項目目錄中存放一個元數據目錄,名稱為“.”前綴加其主命令名。例如,Git會在檢出的項目目錄中加入一個名為“.git”的子目錄。所以,這樣就很容易判定代碼包所用的版本控制系統。另外,又由于代碼包已經存在,我們只需通過代碼版本控制系統的更新命令來更新代碼包,因此也就不需要知道其遠程倉庫的URL了。對于已存在于本地工作區的代碼包,除非要求強行更新代碼包,否則go get
命令不會進行重復下載。如果想要強行更新代碼包,可以在執行go get
命令時加入-u
標記。這一標記會稍后介紹。
如果本地工作區中不存在該代碼包,那么就只能通過對代碼包遠程導入路徑進行分析來獲取相關信息了。首先,go get
命令會對代碼包遠程導入路徑進行靜態分析。為了使分析過程更加方便快捷,go get
命令程序中已經預置了幾個著名代碼托管網站的信息。如下表:
表0-3 預置的代碼托管站點的信息
名稱 | 主域名 | 支持的VCS | 代碼包遠程導入路徑示例 |
---|---|---|---|
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 |
一般情況下,代碼包遠程導入路徑中的第一個元素就是代碼托管網站的主域名。在靜態分析的時候,go get
命令會將代碼包遠程導入路徑與預置的代碼托管站點的主域名進行匹配。如果匹配成功,則在對代碼包遠程導入路徑的初步檢查后返回正常的返回值或錯誤信息。如果匹配不成功,則會再對代碼包遠程導入路徑進行動態分析。至于動態分析的過程,我就不在這里詳細展開了。
如果對代碼包遠程導入路徑的靜態分析或/和動態分析成功并獲取到對應的版本控制系統和遠程倉庫URL,那么go get
命令就會進行代碼包檢出或更新的操作。隨后,go get
命令會在必要時以同樣的方式檢出或更新這個代碼包的所有依賴包。
自定義代碼包遠程導入路徑
如果你想把你編寫的(被托管在不同的代碼托管網站上的)代碼包的遠程導入路徑統一起來,或者不希望讓你的代碼包中夾雜某個代碼托管網站的域名,那么你可以選擇自定義你的代碼包遠程導入路徑。這種自定義的實現手段叫做“導入注釋”。導入注釋的寫法示例如下:
package analyzer // import "hypermind.cn/talon/analyzer"
代碼包analyzer
實際上屬于我的一個網絡爬蟲項目。這個項目的代碼被托管在了Github網站上。它的網址是:https://github.com/hyper-carrot/talon。如果用標準的導入路徑來下載analyzer
代碼包的話,命令應該這樣寫go get github.com/hyper-carrot/talon/analyzer
。不過,如果我們像上面的示例那樣在該代碼包中的一個源碼文件中加入導入注釋的話,這樣下載它就行不通了。我們來看一看這個導入注釋。
導入注釋的寫法如同一條代碼包導入語句。不同的是,它出現在了單行注釋符//
的右邊,因此Go語言編譯器會忽略掉它。另外,它必須出現在源碼文件的第一行語句(也就是代碼包聲明語句)的右邊。只有符合上述這兩個位置條件的導入注釋才是有效的。再來看其中的引號部分。被雙引號包裹的應該是一個符合導入路徑語法規則的字符串。其中,hypermind.cn
是我自己的一個域名。實際上,這也是用來替換掉我想隱去的代碼托管網站域名及部分路徑(這里是github.com/hyper-carrot
)的那部分。在hypermind.cn
右邊的依次是我的項目的名稱以及要下載的那個代碼包的相對路徑。這些與其標準導入路徑中的內容都是一致的。為了清晰起見,我們再來做下對比。
github.com/hyper-carrot/talon/analyzer // 標準的導入路徑
hypermind.cn /talon/analyzer // 導入注釋中的導入路徑
你想用你自己的域名替換掉標準導入路徑中的哪部分由你自己說了算。不過一般情況下,被替換的部分包括代碼托管網站的域名以及你在那里的用戶ID就可以了。這足以達到我們最開始說的那兩個目的。
雖然我們在talon項目中的所有代碼包中都加入了類似的導入注釋,但是我們依然無法通過go get hypermind.cn/talon/analyzer
命令來下載這個代碼包。因為域名hypermind.cn
所指向的網站并沒有加入相應的處理邏輯。具體的實現步驟應該是這樣的:
編寫一個可處理HTTP請求的程序。這里無所謂用什么編程語言去實現。當然,我推薦你用Go語言去做。
將這個處理程序與hypermind.cn/talon
這個路徑關聯在一起,并總是在作為響應的HTML文檔的頭中寫入下面這行內容:
<meta name="go-import" content="hypermind.cn/talon git https://github.com/hyper-carrot/talon">
hypermind.cn/talon/analyzer熟悉HTML的讀者都應該知道,這行內容會被視為HTML文檔的元數據。它實際上go get
命令的文檔中要求的寫法。它的模式是這樣的:
<meta name="go-import" content="import-prefix vcs repo-root">
實際上,content
屬性中的import-prefix
的位置上應該填入我們自定義的遠程代碼包導入路徑的前綴。這個前綴應該與我們的處理程序關聯的那個路徑相一致。而vcs
顯然應該代表與版本控制系統有關的標識。還記得表0-2中的主命令列嗎?這里的填入內容就應該該列中的某一項。在這里,由于talon項目使用的是Git,所以這里應該填入git
。至于repo-root
,它應該是與該處理程序關聯的路徑對應的Github網站的URL。在這里,這個路徑是hypermind.cn/talon
,那么這個URL就應該是https://github.com/hyper-carrot/talon
。后者也是talon項目的實際網址。
好了,在我們做好上述處理程序之后,go get hypermind.cn/talon/analyzer
命令的執行結果就會是正確的。analyzer
代碼包及其依賴包中的代碼會被下載到GOPATH環境變量中的第一個工作區目錄的src子目錄中,然后被編譯并安裝。
注意,具體的代碼包源碼存放路徑會是/home/hc/golang/lib/src/hypermind.cn/talon/analyzer。也就是說,存放路徑(包括代碼包源碼文件以及相應的歸檔文件的存放路徑)會遵循導入注釋中的路徑(這里是hypermind.cn/talon/analyzer
),而不是原始的導入路徑(這里是github.com/hyper-carrot/talon/analyzer
)。另外,我們只需在talon項目的每個代碼包中的某一個源碼文件中加入導入注釋,但這些導入注釋中的路徑都必須是一致的。在這之后,我們就只能使用hypermind.cn/talon/
作為talon項目中的代碼包的導入路徑前綴了。一個反例如下:
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"
與自定義的代碼包遠程導入路徑有關的內容我們就介紹到這里。從中我們也可以看出,Go語言為了讓使用者的項目與代碼托管網站隔離所作出的努力。只要你有自己的網站和一個不錯的域名,這就很容易搞定并且非常值得。這會在你的代碼包的使用者面前強化你的品牌,而不是某個代碼托管網站的。當然,使你的代碼包導入路徑整齊劃一是最直接的好處。
OK,言歸正傳,我下面繼續關注go get
這個命令本身。
命令特有標記
go get
命令可以接受所有可用于go build
命令和go install
命令的標記。這是因為go get
命令的內部步驟中完全包含了編譯和安裝這兩個動作。另外,go get
命令還有一些特有的標記,如下表所示:
表0-4 go get
命令的特有標記說明
標記名稱 | 標記描述 |
---|---|
-d | 讓命令程序只執行下載動作,而不執行安裝動作。 |
-f | 僅在使用-u 標記時才有效。該標記會讓命令程序忽略掉對已下載代碼包的導入路徑的檢查。如果下載并安裝的代碼包所屬的項目是你從別人那里Fork過來的,那么這樣做就尤為重要了。 |
-fix | 讓命令程序在下載代碼包后先執行修正動作,而后再進行編譯和安裝。 |
-insecure | 允許命令程序使用非安全的scheme(如HTTP)去下載指定的代碼包。如果你用的代碼倉庫(如公司內部的Gitlab)沒有HTTPS支持,可以添加此標記。請在確定安全的情況下使用它。 |
-t | 讓命令程序同時下載并安裝指定的代碼包中的測試源碼文件中依賴的代碼包。 |
-u | 讓命令利用網絡來更新已有代碼包及其依賴包。默認情況下,該命令只會從網絡上下載本地不存在的代碼包,而不會更新已有的代碼包。 |
為了更好的理解這幾個特有標記,我們先清除Lib工作區的src目錄和pkg目錄中的所有子目錄和文件。現在我們使用帶有-d
標記的go get
命令來下載同樣的代碼包:
hc@ubt:~$ go get -d github.com/hyper-carrot/go_lib/logging
現在,讓我們再來看一下Lib工作區的目錄結構:
/home/hc/golang/lib:
bin/
pkg/
src/
github.com/
hyper-carrot/
go_lib/
logging/
...
我們可以看到,go get
命令只將代碼包下載到了Lib工作區的src目錄,而沒有進行后續的編譯和安裝動作。這個加入-d
標記的結果。
再來看-fix
標記。我們知道,絕大多數計算機編程語言在進行升級和演進過程中,不可能保證100%的向后兼容(Backward Compatibility)。在計算機世界中,向后兼容是指在一個程序或者代碼庫在更新到較新的版本后,用舊的版本程序創建的軟件和系統仍能被正常操作或使用,或在舊版本的代碼庫的基礎上編寫的程序仍能正常編譯運行的能力。Go語言的開發者們已想到了這點,并提供了官方的代碼升級工具——fix
。fix
工具可以修復因Go語言規范變更而造成的語法級別的錯誤。關于fix
工具,我們將放在本節的稍后位置予以說明。
假設我們本機安裝的Go語言版本是1.5,但我們的程序需要用到一個很早之前用Go語言的0.9版本開發的代碼包。那么我們在使用go get
命令的時候可以加入-fix
標記。這個標記的作用是在檢出代碼包之后,先對該代碼包中不符合Go語言1.5版本的語言規范的語法進行修正,然后再下載它的依賴包,最后再對它們進行編譯和安裝。
標記-u
的意圖和執行的動作都比較簡單。我們在執行go get
命令時加入-u
標記就意味著,如果在本地工作區中已存在相關的代碼包,那么就是用對應的代碼版本控制系統的更新命令更新它,并進行編譯和安裝。這相當于強行更新指定的代碼包及其依賴包。我們來看如下示例:
hc@ubt:~$ go get -v github.com/hyper-carrot/go_lib/logging
因為我們在之前已經檢出并安裝了這個代碼包,所以我們執行上面這條命令后什么也沒發生。還記得加入標記-v
標記意味著會打印出被構建的代碼包的名字嗎?現在我們使用標記-u
來強行更新代碼包:
hc@ubt:~$ go get -v -u github.com/hyper-carrot/go_lib/logging
github.com/hyper-carrot/go_lib (download)
其中,“(download)”后綴意味著命令從遠程倉庫檢出或更新了該行顯示的代碼包。如果我們要查看附帶-u
的go get
命令到底做了些什么,還可以加上一個-x
標記,以打印出用到的命令。讀者可以自己試用一下它。
智能的下載
命令go get
還有一個很值得稱道的功能。在使用它檢出或更新代碼包之后,它會尋找與本地已安裝Go語言的版本號相對應的標簽(tag)或分支(branch)。比如,本機安裝Go語言的版本是1.x,那么go get
命令會在該代碼包的遠程倉庫中尋找名為“go1”的標簽或者分支。如果找到指定的標簽或者分支,則將本地代碼包的版本切換到此標簽或者分支。如果沒有找到指定的標簽或者分支,則將本地代碼包的版本切換到主干的最新版本。
前面我們說在執行go get
命令時也可以加入-x
標記,這樣可以看到go get
命令執行過程中所使用的所有命令。不知道讀者是否已經自己嘗試了。下面我們還是以代碼包github.com/hyper-carrot/go_lib
為例,并且通過之前示例中的命令的執行此代碼包已經被檢出到本地。這時我們再次更新這個代碼包:
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-refcd /home/hc/golang/lib/src/github.com/hyper-carrot/go_lib
git checkout origin/masterWORK=/tmp/go-build034263530
在上述示例中,go get
命令通過git fetch
命令將所有遠程分支更新到本地,而后有用git show-ref
命令列出本地和遠程倉庫中記錄的代碼包的所有分支和標簽。最后,當確定沒有名為“go1”的標簽或者分支后,go get
命令使用git checkout origin/master
命令將代碼包的版本切換到主干的最新版本。下面,我們在本地增加一個名為“go1”的標簽,看看go get
命令的執行過程又會發生什么改變:
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
將這兩個示例進行對比,我們會很容易發現它們之間的區別。第二個示例的命令執行過程中使用git show-ref
查看所有分支和標簽,當發現有匹配的信息又通過git show-ref tags/go1 origin/go1
命令進行精確查找,在確認無誤后將本地代碼包的版本切換到標簽“go1”之上。命令go get
的這一功能是非常有用的。我們的代碼在直接或間接依賴某些同時針對多個Go語言版本開發的代碼包時,可以自動的檢出其正確的版本。也可以說,go get
命令內置了一定的代碼包多版本依賴管理的功能。
以上就是“go get命令的作用是什么”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。