大名鼎鼎的 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.2
vgo: finding rsc.io/quote v1.5.2
vgo: finding rsc.io/sampler v1.3.0
vgo: finding golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
vgo: downloading rsc.io/quote v1.5.2
vgo: downloading rsc.io/sampler v1.3.0
vgo: 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.… 获取指定版本,并修改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 VERSION
github.com/you/hello -
golang.org/x/text v0.0.0-20180208041248-4e4a3210bb54
rsc.io/quote v1.5.2
=> ../quote
rsc.io/sampler v1.3.1
三、退到vendor 兼容不使用vgo的用户
有一种场景叫做和谐共处,我想使用vgo,但是构建我项目的人不想使用vgo,想用标准的go build构建,vgo也是可以的。
首先把项目放在gopath下,然后执行
vgo vendor
vgo就会把所有依赖都放在vendor目录下,这样go build直接就可以运行啦!
四、需要注意的几点
- 在vgo-import文章中(Semantic Import Versioning),提出了避免单例问题,同时依赖多版本的库,如果这个库在初始化时候有单例和相关操作,有可能会冲突,如都向默认的http 路由注册handler。
- 目前vgo的文档似乎还不是很健全,代码也还有一些bug,在生产环境可能还不适合去使用。