Go的新玩具 vgo

大名鼎鼎的 Russ Cox 在18年2月20日在他的博客上介紹了他為go設計的新工具,版本化的golang包管理工具——vgo

vgo versioned go的縮寫,意即帶版本的go,從功能上類比java的maven,rust的cargo,node的npm,golang現有的dep等,但是有所不同。

〇、需要準備的概念

在這個新鮮出爐的vgo工具,我個人認為有一個非常重要也非常值得一提的概念稱之為:語義導入版本(英文Semantic Import Versioning )。

先看兩個在golang社區非常常見的兩個版本概念。

  • 語義版本 (Semantic Versioning):典型代表 dep ( github.com/golang/dep ) 。使用版本控制的tag等表明包的版本,正確的寫法如 v2.3.4 。其中2是主版本號,3是小版本號,4是補丁版本號。顧名思義,小版本號往往是添加新的特性,補丁版本號是補補修修。優點是精準選擇版本,避免坑。
  • 導入版本 ( Import Versioning ) : 典型代表 gopkg ( gopkg.in ) , 具體使用者如go-redis ( gopkg.in/redis.v3 ),即包名中包含版本號,通過go get特性實現,具體參見gopkg官方說明。好處是非常方便更新修復bug。

那麼什麼是語義導入版本,也就呼之欲出了,即貪心的人兩個都要。

即在包路徑上寫明主版本號,也同時使用語義版本

一、擼起袖子 上手就干

輸入命令行安裝

go get golang.org/x/vgo

(假設你本地安裝的是最新的golang,且GOPATH什麼的都配置好了 @.@ )

在任意目錄創建一個名為hello的文件夾,同時創建一個main.go,並寫入下面的代碼(代碼和整個例子都來自源網站 )。

package main // import "github.com/you/hello"import ( "fmt" "rsc.io/quote")func main() { fmt.Println(quote.Hello())}

創建一個空的go.mod 文件在這個目錄下面(PS: 這個文件像maven的pom.xml、npm的package.json,裡面會有當前的包下的庫依賴,當然現在還是空的)。

touch go.mod

在目錄下運行下面的命令,使用vgo構建這個簡單的hello程序

vgo build

輸出的內容如下所示

vgo: resolving import "rsc.io/quote"vgo: finding rsc.io/quote (latest)vgo: adding rsc.io/quote v1.5.2vgo: finding rsc.io/quote v1.5.2vgo: finding rsc.io/sampler v1.3.0vgo: finding golang.org/x/text v0.0.0-20170915032832-14c0d48ead0cvgo: downloading rsc.io/quote v1.5.2vgo: downloading rsc.io/sampler v1.3.0vgo: downloading golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c

這個時候hello就構建完成了,運行./hello 可以輸出十分親切的「你好,世界」。

而此時go.mod里也自動生成了依賴關係,文件內容被修改成了:

module "github.com/you/hello"require "rsc.io/quote" v1.5.2

module 指示這個模塊的包路徑。

require 顧名思義,即依賴XX包的v.x.x.x 版本。

(PS: 雖然這個地方感覺比較疑惑,自定義的格式真的好嗎,是不是使用比如toml什麼的標準的驗證過的文件格式更好呢?)

二、vgo的其他用法

  • vgo list -m 查看所有依賴
  • vgo list -m -u 查看所有依賴同時檢查更新,會列印出最新版本和當前版本
  • vgo test all 執行所有測試,包括依賴包的測試
  • vgo test rsc.io/sampler 執行指定包測試
  • vgo get -u 更新所有依賴
  • vgo list -t rsc.io/sampler 檢查指定包所有可用的版本 即tag
  • vgo get rsc.io/sampler@v1.3.1 獲取指定版本,並修改go.mod

排除指定版本:指明不使用版本,這個時候需要手改go.mod,添加一行如

exclude "rsc.io/sampler" v1.99.99

替換依賴:替換依賴包,go.mod語法如下

replace "rsc.io/quote" v1.5.2 => "github.com/you/quote" v0.0.0-myfork

也可以替換成本地文件夾

replace "rsc.io/quote" v1.5.2 => "../quote"

這樣vgo就會替換這個依賴,vgo list -m 時候也會顯出這個箭頭表示替換。

MODULE VERSIONgithub.com/you/hello -golang.org/x/text v0.0.0-20180208041248-4e4a3210bb54rsc.io/quote v1.5.2 => ../quotersc.io/sampler v1.3.1

三、退到vendor 兼容不使用vgo的用戶

有一種場景叫做和諧共處,我想使用vgo,但是構建我項目的人不想使用vgo,想用標準的go build構建,vgo也是可以的。

首先把項目放在gopath下,然後執行

vgo vendor

vgo就會把所有依賴都放在vendor目錄下,這樣go build直接就可以運行啦!

四、需要注意的幾點

  1. 在vgo-import文章中(Semantic Import Versioning),提出了避免單例問題,同時依賴多版本的庫,如果這個庫在初始化時候有單例和相關操作,有可能會衝突,如都向默認的http 路由註冊handler。
  2. 目前vgo的文檔似乎還不是很健全,代碼也還有一些bug,在生產環境可能還不適合去使用。

推薦閱讀:

TAG:Go語言 | 包管理器 | Go編程 |