Python 程式設計師的 Golang 學習指南(IV): 包管理篇

Cloudinsight發表於2016-10-19

Authors: startover


第一篇文章我們有提到,Golang 官方並沒有推薦最佳的包管理方案,對於像我這樣習慣了 Python 包管理的開發者,自然還是希望有像 pip 一樣好用的工具,幫助我們進行依賴管理,下面就讓我們對 Golang 的包管理機制一探究竟。

Golang 包管理機制

Go 語言的包管理系統是去中心化的,我們可以通過 go get 命令獲取存放在遠端倉庫的程式碼協議。實際上,go get 支援以下 VCS 協議:

名稱 主命令 說明
Mercurial hg Mercurial 是一種輕量級分散式版本控制系統,採用 Python 語言實現,易於學習和使用,擴充套件性強。
Git git Git 最開始是 Linux Torvalds 為了幫助管理 Linux 核心開發而開發的一個開源的分散式版本控制軟體。但現在已被廣泛使用。它是被用來進行有效、高速的各種規模專案的版本管理。
Subversion svn Subversion 是一個版本控制系統,也是第一個將分支概念和功能納入到版本控制模型的系統。但相對於 Git 和 Mercurial 而言,它只算是傳統版本控制系統的一員。
Bazaar bzr Bazaar 是一個開源的分散式版本控制系統。但相比而言,用它來作為 VCS 的專案並不多。

比如,我們現在需要獲取 godep 這個專案,可以執行如下命令:

$ go get github.com/tools/godep

需要指出的是,go get 實際上執行了兩個步驟:1. 下載原始碼包;2. 執行 go install,如果只下載不安裝,則需要指定 -d 引數,如下:

$ go get -d github.com/tools/godep

除了 go get,Go 語言還提供了一個 Workspace 的機制,即通過設定 GOPATH 環境變數,指定除了 GOROOT 所指定的目錄之外,Go 程式碼所在的位置 (也就是 Workspace 的位置)。 一般來說,GOPATH 目錄下會包含 pkg、src 和 bin 三個子目錄,這三個目錄各有用處。

  • bin 目錄用於放置編譯好的可執行檔案,為了使得這裡的可執行檔案可以方便的執行, 可在 shell 中設定 PATH 環境變數。
  • src 目錄用於放置程式碼原始檔,在進行 import 時,是使用這個位置作為根目錄的。自己編寫的程式碼也應該放在這下面。
  • pkg 用來放置安裝的包的連結物件 (Object) 的。這個概念有點類似於連結庫,Go 會將編譯出的可連線庫放在這裡, 方便編譯時連結。不同的系統和處理器架構的物件會在 pkg 存放在不同的資料夾中。

Golang 包管理現狀

顯然,通過 go getWorkspace 的方式並不足以解決專案依賴和版本依賴的問題,主要有以下幾點:

  1. 第三方包的版本控制。如果沒有明確指定依賴的第三方包的版本,團隊開發很容易匯入不一樣的版本,導致專案無法正常執行。
  2. 第三方包沒有內容安全審計,很容易引入程式碼 Bug,這是泛中心化包管理普遍存在的問題。
  3. 依賴的完整性無法校驗,程式編譯時無法保障百分百成功。

因此,我們必須藉助第三方工具來解決這些問題。

第三方解決方案

這裡我從官方推薦包管理工具中挑選了幾個比較常用的工具:Godep, Govendor 以及 Glide,作下簡單介紹。

Godep

  • godep save

這個命令做了以下幾件事:

> 1. 查詢專案中所用到的所有的第三方包。 > 2. 在專案目錄下建立 Godeps 目錄,Godeps/Godeps.json 是依賴檔案,包括了 go 的版本,用到的第三方包的引入路徑,版本號等資訊,json 檔案需要一併加入到版本控制裡。 > 3. 所有依賴的第三方包的程式碼會被拷貝到 vendor/ 下,並且移除了 .git 這樣的版本控制資訊。

  • godep restore

當下載別人釋出的專案時,如果下載的專案中只有 Godeps.json 檔案,而沒有包含第三方包,則可以使用 godep restore 這個命令將所有的依賴包下載到 $GOPATH 目錄下,而不用一個一個去 go get,還是很方便的。

Govendor

  • govendor init

執行 govendor init 會在根目錄下生成一個 vendor 資料夾,以及 vendor/vendor.json,其中 vendor.json 類似 godep 工具中的描述檔案版本的功能。

  • govendor add +external

執行 govendor add +external 會將所有依賴的第三方包的程式碼拷貝到 vendor 資料夾下,並且移除了 .git 這樣的版本控制資訊,測試所需依賴以及依賴專案的測試檔案。與 godep save 的功能類似。

  • govendor fetch

執行 govendor fetch 新增的第三方包直接被 get 到根目錄的 vendor 資料夾下,不會與其它的專案混用第三方包,完美避免了多個專案同用同一個第三方包的不同版本問題。

這樣,我們只需對 vendor/vendor.json 進行版本控制,即可對第三包依賴關係進行控制。

Glide

  • glide init

執行 glide initglide create 會在專案根目錄下生成一個 glide.yaml,這個檔案用來記錄專案用到的第三方包的依賴關係,並支援編輯修改。

  • glide install

執行 glide install,會把所有依賴的第三方包都下載到 vendor 資料夾下,並且會在 glide.yaml 中新增所有依賴的第三方包名稱,以及在 glide.lock 檔案中記錄具體的版本管理資訊。

總結

上面我們分別對 Godep, Govendor 以及 Glide 這三種工具做了簡單的介紹,對於 Python 開發者,個人還是比較認同 Govendor 的方式,因為其很容易實現類似 Virtualenv 的模式,從而實現不同程式使用不同版本依賴的目的。

當然,如果你是 Node.js 的開發者,可能對於 Godep 有更加熟悉的感覺,而對於 Ruby 開發者,gom 會讓你感到更加親切。

因此,針對第三方包管理工具的選擇,現階段還完全交由開發者做裁定,這裡就 “仁者見仁,智者見智” 了。

相關連結:
http://www.infoq.com/cn/articles/golang-package-management
https://io-meter.com/2014/07/30/go's-package-management/
https://github.com/golang/go/wiki/PackageManagementTools


本文章為 Cloudinsight 技術團隊工程師原創,更多技術文章可訪問 Cloudinsight 技術部落格Cloudinsight 為視覺化系統監控工具,涵蓋 Windows、Linux 作業系統,用 Golang 開發的 Cloudinsight Agent 正式開源了,歡迎 fork,Github:https://github.com/cloudinsight/cloudinsight-agent

golang-for-pythonistas 系列持續更新中,歡迎關注~

更多原創文章乾貨分享,請關注公眾號
  • Python 程式設計師的 Golang 學習指南(IV): 包管理篇
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章