目录

​​前言​​

​​即看即用​​

​​Go 包依赖管理工具govendor​​

​​vendor 特性​​

​​vendor 使用建议​​

​​govendor 简介​​

​​govendor 使用​​

​​安装​​

​​初始化​​

​​常用命令​​

​​govendor 子命令​​

​​govendor 状态参数​​

​​Go modules​​

​​ 常见错误​​

​​参考​​

​​ go mod与 govendor 区别与使用​​

​​vendor 目录方式​​

​​解决的问题​​

​​未解决的问题​​

​​什么是 GOROOT 和 GOPATH​​

​​要解决 vendor 目录 未解决的问题,使用 govendor​​

​​govendor​​

​​常用命令​​

​​使用建议​​

​​缺点​​

​​go mod​​

​​go mod​​

​​go mod 与 go vendor 区别​​

​​Golang 管理go类库版本 ​​

​​Go类库版本规则​​

​​Go类库发版示例​​

​​小版本升级​​

​​大版本升级​​

​​使用本地go类库​​

​​结束语​​


前言

go mod 和 govendor 都是 Go 包管理器,类似 Java 工程的 maven

go 包依赖管理史( 按时间出现顺序):

  • 2012年3月 Go 1 发布,此时没有版本的概念
  • 2013年 Golang 团队在 FAQ 中提议开发者保证相同 import path 的兼容性,后来成为一纸空文
  • 2013年10月 Godep
  • 2014年7月 glide
  • 2014年 有人提出 external packages 的概念,在项目的目录下增加一个 vendor 目录来存放外部的包
  • 2015年8月 Go 1.5 实验性质加入 vendor 机制
  • 2015年 有人提出了采用语义化版本的草案
  • 2016年2月 Go 1.6 vendor 机制 默认开启
  • 2016年5月 Go 团队的 Peter Bourgon 建立委员会,讨论依赖管理工具,也就是后面的 dep
  • 2016年8月 Go 1.7: vendor 目录永远启用
  • 2017年1月 Go 团队发布 Dep,作为准官方试验
  • 2018年8月 Go 1.11发布 Modules 作为官方试验
  • 2019年2月 Go 1.12发布 Modules 默认为 auto
  • 2019年9月 Go 1.13 版本默认开启 Go Mod 模式

……

故事:失宠的 Vendor 目录

Vendor目录是Golang从1.5版本开始引入的,为项目开发提供了一种离线保存第三方依赖包的方法。但是到了Golang 1.11之后,由于引入了Module功能,在运行go build时,优先引用的是Module依赖包的逻辑,所以Vendor目录就被“无视”了,进而可能发生编译错误, moudle 说还是很想他,于是 提供了 go mod vendor 命令用来生成 vendor 目录。这样能避免一些编译问题,依赖可以先从 vendor 目录进行扫描。

$ go mod help vendor usage: go mod vendor [-v] Vendor resets the main module's vendor directory to include all packages needed to build and test all the main module's packages. It does not include test code for vendored packages.

这句话的意思是:把 go mod init 后下载的相关依 赖包(Gopath 的 pkg) 目录,拷贝到 vendor 目录。

争议:​https://zhuanlan.zhihu.com/p/59191567​

go mod vendor 只是给的兼容方案。
vendor 目录就不该入代码仓库的。
国内网络问题,goproxy 可完美解决,gomod/athens
至少能用了,代理私有库也没问题。
生产环境 1.11 就开始全面 go mod 的路过。

目前我们公司的开发人员建议使用go mod 代替 govendor

即看即用

govendor 使用

要求:

  • 项目必须在 ​​$GOPATH/src​​ 目录下
  • 如果 Go 版本为 1.5时,则须手动设置环境变量 ​​set GO15VENDOREXPERIMENT=1,1.6以上版本不需要​

安装

​go get -u github.com/kardianos/govendor​

为了方便快捷使用 ​​govendor​​​,建议将 ​​$GOPATH/bin​​ 添加到 PATH 中。Linux/macOS 如下设置:

​export PATH="$GOPATH/bin:$PATH"​

初始化

在项目根目录下执行以下命令进行 ​​vendor​​ 初始化:

​govendor init​

1、govendor list可以快速查看你项目中的外部依赖包。

2、govendor add添加依赖包到vendor目录下,在使用 govendor add命令时,后面需要跟上下面介绍的一些状态,也可以直接跟上缺失包的地址,如下文常见错误中的做法。 
3、govendor update从你的GOPAHT中更新你工程的依赖包 
4、govendor remove从你工程下的vendor文件中移除对应的包 
5、govendor fetch添加或者更新vendor文件夹中的包

govendor使用状态来指定包

1 +local     (l) 表示工程中的包
2 +external  (e) 从GOPATH中引用的包,但不包含在你的当前工程中
3 +vendor    (v) vendor文件夹中的包
4 +std       (s) Go标准库中的包
5 +excluded  (x) 从vendor文件中排除的外部依赖包
6 +unused    (u) vendor文件中存在但却未使用的包
7 +missing   (m) 项目引用但却为发现的包
8 +program   (p) main包中包

  其中有一些状态存在简写,例如:+std可以用+s表示,+external可以用+ext或者+e表示,+external可以用+exc或者+x表示。

在使用时,你也可以对这些状态进行逻辑组合,例如:

1 +local,grogram表示既满足+local又满足+program。
2 +local +vendor表示只要满足两者之一。
3 +vendor,program +std表示vendor和program是与的关系,整体和std是或的关系
4 +vendor,^program表示满足vendor,但却不满足program。

Go 包依赖管理工具govendor

(官方文档:​​https://pkg.go.dev/gitee.com/jaykieq/govendor#section-readme​​)

 转自:​​Go 包依赖管理工具 —— govendor​​ 

​govendor​​​ 是一个基于 ​​vendor​​ 机制实现的 Go 包依赖管理命令行工具。与原生 vendor 无侵入性融合,也支持从其他依赖管理工具迁移,可以很方便的实现同一个包在不同项目中不同版本、以及无相互侵入的开发和管理。

vendor 特性

vendor是go的依赖包管理工具,它将项目依赖的包,特指外部包,复制到当前工程下的vendor目录下,这样go build的时候,会优先从vendor目录寻找依赖包。

将依赖的外部包引进工程下的vendor目录,(随工程到)其他机器上,其他机器就可以直接编译,而不用再去构建外部包的编译环境,一个一个的go get获取外部包(当然你也可以直接拷贝整个GOPATH下的第三方包源码过来,也是起到了vendor相同的作用)。另外,防止了go get 重新拉取的外部包的版本可能和期望的不一致,从而导致编译错误问题

Go 从 1.5 版本开始提供了 vendor 特性,但需要手动设置环境变量 ​​GO15VENDOREXPERIMENT=1 启用。​

在执行 ​​go build​​​ 或 ​​go run​​ 命令时,会按照以下顺序去查找包:

  • 当前包下的 vendor 目录
  • 向上级目录查找,直到找到 src 下的 vendor 目录
  • 在 GOROOT 目录下查找
  • 在 GOPATH 下面查找依赖包

发布 1.6 版本时,该环境变量的值已经默认设置为 1 了,该值可以使用 ​​go env​​ 命令查看。

发布 1.7 版本时,已去掉该环境变量,默认开启 ​​vendor​​ 特性。

vendor 使用建议

  • 一个库工程(不包含 ​​main​​ 的 ​​package​​)不应该在自己的版本控制中存储外部的包在 ​​vendor​​ 目录中,除非有特殊原因并且知道为什么要这么做。
  • 在一个应用中,(包含 ​​main​​ 的 ​​package​​),建议只有一个 ​​vendor​​ 目录,且在代码库一级目录。

govendor 简介

​govendor​​​ 是一个基于 ​​vendor​​ 目录机制的包管理工具。

  • 支持从项目源码中分析出依赖的包,并从 ​​$GOPATH​​​ 复制到项目的 ​​vendor​​ 目录下
  • 支持包的指定版本,并用 ​​vendor/vendor.json​​​ 进行包和版本管理,这点与 PHP 的 ​​Composer​​ 类似
  • 支持用 ​​govendor add/update​​​ 命令从 ​​$GOPATH​​ 中复制依赖包
  • 如果忽略了 ​​vendor/*/​​​ 文件,可用 ​​govendor sync​​ 恢复依赖包
  • 可直接用 ​​govendor fetch​​ 添加或更新依赖包
  • 可用 ​​govendor migrate​​​ 从其他 ​​vendor​​​ 包管理工具中一键迁移到 ​​govendor​
  • 支持 Linux,macOS,Windows,甚至现有所有操作系统
  • 支持 Git、Hg、SVN,BZR(必须指定一个路径)

govendor 使用

要求:

  • 项目必须在 ​​$GOPATH/src​​ 目录下
  • 如果 Go 版本为 1.5,则必须手动设置环境变量 ​​set GO15VENDOREXPERIMENT=1​

安装

​go get -u github.com/kardianos/govendor​

#go get -u github.com/kardianos/govendor下载govendor工具到本地,一般在$GOPATH/bin目录下,可以用updatedb&&locate govendor|grep -w govendor 查看

为了方便快捷使用 ​​govendor​​​,建议将 ​​$GOPATH/bin​​ 添加到 PATH 中。Linux/macOS 如下设置:

​export PATH="$GOPATH/bin:$PATH"​

初始化

在项目根目录下执行以下命令进行 ​​vendor​​ 初始化:

cd "my project in GOPATH"

  1. ​govendor init​

项目根目录下即会自动生成 ​​vendor​​​ 目录和 ​​vendor.json​​​ 文件。此时 ​​vendor.json​​ 文件内容为:

​{​

​"comment": "",​

​"ignore": "test",​

​"package": [],​

​"rootPath": "govendor-example"​

​}​

常用命令

  • 将已被引用且在 ​​$GOPATH​​​ 下的所有包复制到 ​​vendor​​ 目录

​govendor add +external​

  • 仅从 ​​$GOPATH​​ 中复制指定包

​govendor add gopkg.in/yaml.v2​

  • 列出代码中所有被引用到的包及其状态(可以快速查看你项目中的外部依赖包。)

​govendor list​

​e github.com/gin-contrib/sse​

​e github.com/gin-gonic/gin​

​e github.com/gin-gonic/gin/binding​

​e github.com/gin-gonic/gin/internal/json​

​e github.com/gin-gonic/gin/render​

​e github.com/golang/protobuf/proto​

​e github.com/mattn/go-isatty​

​e github.com/ugorji/go/codec​

​e gopkg.in/go-playground/validator.v8​

​e gopkg.in/yaml.v2​

​pl govendor-example​

​m github.com/json-iterator/go​

​m golang.org/x/sys/unix​

  • 列出一个包被哪些包引用

​govendor list -v fmt​

​s fmt​

​├── e github.com/gin-contrib/sse​

​├── e github.com/gin-gonic/gin​

​├── e github.com/gin-gonic/gin/render​

​├── e github.com/golang/protobuf/proto​

​├── e github.com/ugorji/go/codec​

​├── e gopkg.in/go-playground/validator.v8​

​├── e gopkg.in/yaml.v2​

​└── pl govendor-example​

  • 从远程仓库添加或更新某个包(不会在 ​​$GOPATH​​ 也存一份)

​govendor fetch golang.org/x/net/context​

  • 安装指定版本的包

​govendor fetch golang.org/x/net/context@a4bbce9fcae005b22ae5443f6af064d80a6f5a55​

​govendor fetch golang.org/x/net/context@v1 # Get latest v1.*.* tag or branch.​

​govendor fetch golang.org/x/net/context@=v1 # Get the tag or branch named "v1".​

  • 只格式化项目自身代码(​​vendor​​ 目录下的不变动)

​govendor fmt +local​

  • 只构建编译项目内部的包

​govendor install +local​

  • 只测试项目内部的测试案例

​govendor test +local​

  • 构建所有 ​​vendor​​ 包

​govendor install +vendor,^program​

  • 拉取所有依赖的包到 ​​vendor​​​ 目录(包括 ​​$GOPATH​​ 存在或不存在的包)

​govendor fetch +out​

  • 包已在 ​​vendor​​​ 目录,但想从 ​​$GOPATH​​ 更新

​govendor update +vendor​

  • 已修改了 ​​$GOPATH​​​ 里的某个包,现在想将已修改且未提交的包更新到 ​​vendor​

​govendor update -uncommitted <updated-package-import-path>​

  • Fork 了某个包,但尚未合并,该如何引用到最新的代码包

​govendor fetch github.com/normal/pkg::github.com/myfork/pkg​

此时将从 ​​myfork​​​ 拉取代码,而不是 ​​normal​​。

  • ​vendor.json​​ 中记录了依赖包信息,该如何拉取更新

​govendor sync​

govendor 子命令

各子命令详细用法可通过 ​​govendor COMMAND -h​​​ 或阅读 ​​github.com/kardianos/govendor/context​​ 查看源码包如何实现的。

子命令

功能

init

创建 ​​vendor​​​ 目录和 ​​vendor.json​​ 文件

list

列出&过滤依赖包及其状态

add

从 ​​$GOPATH​​​ 复制包到项目 ​​vendor​​ 目录

update

从 ​​$GOPATH​​​ 更新依赖包到项目 ​​vendor​​ 目录

remove

从 ​​vendor​​ 目录移除依赖的包

status

列出所有缺失、过期和修改过的包

fetch

从远程仓库添加或更新包到项目 ​​vendor​​​ 目录(不会存储到 ​​$GOPATH​​)

sync

根据 ​​vendor.json​​​ 拉取相匹配的包到 ​​vendor​​ 目录

migrate

从其他基于 ​​vendor​​ 实现的包管理工具中一键迁移

get

与 ​​go get​​​ 类似,将包下载到 ​​$GOPATH​​​,再将依赖包复制到 ​​vendor​​ 目录

license

列出所有依赖包的 LICENSE

shell

可一次性运行多个 ​​govendor​​ 命令

govendor 状态参数

状态

缩写

含义

+local

l

本地包,即项目内部编写的包,即项目自身的包组织

+external

e

外部包,即在 ​​GOPATH​​​ 中、却不在项目 ​​vendor​​ 目录

+vendor

v

已被 govendor 管理,即在 vendor 目录下

+std

s

标准库里的包

+excluded

x

明确被排除的外部包

+unused

u

未使用的包,即在 ​​vendor​​ 目录下,但项目中并未引用到

+missing

m

被引用了但却找不到的包

+program

p

主程序包,即可被编译为执行文件的包

+outside

相当于状态为 ​​+external +missing​

+all

所有包

支持状态参数的子命令有:​​list​​​、​​add​​​、​​update​​​、​​remove​​​、​​fetch​

Package specifier

​完整的包规范是:<path>[::<origin>][{/...|/^}][@[<version-spec>]]​

一些例子:

  • ​github.com/kardianos/govendor​​ 指定单个包和单个文件夹。
  • ​github.com/kardianos/govendor/...​​ 指定 govendor 和该路径下的所有引用包。
  • ​github.com/kardianos/govendor/^​​​ specifies the ​​govendor​​ folder and all sub-folders. Useful for resources or if you don't want a partial repository.
  • ​github.com/kardianos/govendor/^::github.com/myself/govendor​​ same as above but fetch from user "myself".
  • ​github.com/kardianos/govendor/...@abc12032​​  修订版 abc12032 中所有引用的软件包。
  • ​github.com/kardianos/govendor/...@v1​​ 同上,但获取最新的“v1”标签,例如“v1.4.3”。
  • ​github.com/kardianos/govendor/...@=v1​​ 获取确切的版本“v1”。

Go modules

普大喜奔的是,从 Go 1.11 版本开始,官方已内置了更为强大的 ​​Go modules​​​ 来一统多年来 Go 包依赖管理混乱的局面(Go 官方之前推出的 ​​dep​​ 工具也几乎胎死腹中),并且将在 1.13 版本中正式默认开启。

目前已受到社区的看好和强烈推荐,建议新项目采用 Go modules。

版本管理

​https://zhuanlan.zhihu.com/p/103914406​​)

不要将整个 ​​vendor/​​​ 目录的内容都提到 git 仓库,只提交 ​​vendor/vendor.json​​ 文件就可以了。

当我们拉代码之后,需要安装依赖包时,只需要执行下面这条命令就可以了。

govendor sync

​.gitignore​​ 文件,重点在最后两行:

# Created by https://www.gitignore.io/api/go
### Go ###
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, build with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out

### Go Patch ###
/vendor/
!/vendor/vendor.json

所以,一般的开发流程可以这样来做:如果是新建项目,先安装 govendor 并初始化,然后通过 govendor 来安装依赖包;如果是已有项目,先从版本库拉下来,然后安装 govendor,再执行同步命令即可。

 常见错误

1、服务器提示某个依赖包没有找到

  原因可能是vendor文件中没有该包或者vendor.json文件中没有该包的描述信息。

  假设"github.com/astaxie/beego/logs"包的信息在vendor.json文件中没有找到,则在go命令行中执行govendor add github.com/astaxie/beego/logs。

Go. command not found: govendor.

是因为没有把 $GOPATH/bin 加入 PATH 中, 在自己使用的bash中加入:👇,关闭,然后执行 source .zshrc(自己使用的bash)

export PATH=$PATH:$GOPATH/bin

$GOPATH 是Go设置的env

 

参考

 go mod与 govendor 区别与使用

(转自:​​https://developer.aliyun.com/article/937944​​)

vendor 目录方式


go vendor 是go 1.5 官方引入管理包依赖的方式

基本思路: 将引用的外部包的源代码放在当前工程的vendor目录下面,go 1.6以后编译go代码会优先从vendor目录先寻找依赖包;找不到再从GOPATH 中寻找


解决的问题

将源码拷贝到当前目录下,这样导包当前工程代码到任意的机器的 ¥GOPATH/src 都可以编译通过,避免项目代码外部依赖过多

未解决的问题

无法精确的引用 外部包进行版本控制,不能指定引用某个特定版本的外部包,只是在开发时将其拷贝过来,但是一旦外部包升级,vendor 下面的包会跟着升级,而且 vendor 下面没有完整的引用包的版本信息, 对包升级带来了无法评估的风险。

什么是 GOROOT 和 GOPATH

  • GOROOT:golang的安装路径,当安装好go之后,默认会安装在/usr/local/go之下。GOROOT的主要作用是标识go的当前安装位置。
  • GOPATH:存放SDK以外的第三方类库;收藏的可复用的代码,包含三个子目录:-- src : 存放项目源码文件 -- pkg : 编译后的包文件 -- bin :编译后生成的可执行文件

要解决 vendor 目录 未解决的问题,使用 govendor

  • 可以平滑的将现有非 vendor 项目转换成 vendor 项目

govendor add inport_out_packagename


  • 会生成一个元数据文件,记录工程依赖的外部包,及其版本信息

vendor.json


  • 提高命令查看整个工程的依赖关系

goverdor --list goverdor --list -v


govendor


govendor 是一个基于 vendor 机制实现的 Go 包依赖管理命令行工具。与原生 vendor 无侵入性融合,也支持从其他依赖管理工具迁移,可以很方便的实现同一个包在不同项目中不同版本、以及无相互侵入的开发和管理。


在执行 go build 或 go run 命令时,会按照以下顺序去查找包:

  • 当前包下的 vendor 目录
  • 向上级目录查找,直到找到 src 下的 vendor 目录
  • 在 GOROOT 目录下查找
  • 在 GOPATH 下面查找依赖包

常用命令


【vendor】Go 包依赖管理工具govendor_golang

【vendor】Go 包依赖管理工具govendor_java_02

  1. 安装


go get -u -v github.com/kardianos/govendor


  1. 初始化


cd xxx govendor init


初始化完成后,项目目录中会生成一个vendor文件夹,包含一个vendor.json文件,json文件中包含了项目所依赖的所有包信息


{ "comment": "", "ignore": "test", "package": [], "rootPath": "govendor-example" }


将已被引用且在 $GOPATH 下的所有包复制到 vendor 目录


govendor add +external


仅从 $GOPATH 中复制指定包


govendor add gopkg.in/yaml.v2


列出代码中所有被引用到的包及其状态


govendor list


运行结果


e github.com/gin-contrib/sse e github.com/gin-gonic/gin e github.com/gin-gonic/gin/binding e github.com/gin-gonic/gin/internal/json e github.com/gin-gonic/gin/render e github.com/golang/protobuf/proto e github.com/mattn/go-isatty e github.com/ugorji/go/codec e gopkg.in/go-playground/validator.v8 e gopkg.in/yaml.v2 pl govendor-example m github.com/json-iterator/go m golang.org/x/sys/unix


列出一个包被哪些包引用


govendor list -v fmt


s fmt ├── e github.com/gin-contrib/sse ├── e github.com/gin-gonic/gin ├── e github.com/gin-gonic/gin/render ├── e github.com/golang/protobuf/proto ├── e github.com/ugorji/go/codec ├── e gopkg.in/go-playground/validator.v8 ├── e gopkg.in/yaml.v2 └── pl govendor-example


使用建议

  • 使用govendor管理项目并进行项目协作时,我们每次不需要提交整个vendor目录,而只需要提交json文件,十分方便。一个配置文件全部搞定!
  • vendor 目录解决了工程依赖打包的问题,可将依赖与工程一起打包,减少下载依赖的时间。
  • 同一个项目只创建一个govendor目录,且在代码库的一级目录。

缺点

  • 依赖包全部都在vendor目录下,每个项目都有一份,所以每次拉取项目时都会拉一遍依赖。
  • govendor不区分包版本,意味着开发期间拉的依赖的包很可能跟上线后的拉的依赖包版本不一致,很危险。
  • govendor add +e会拉取全部外部包,即使是本项目没有用到的,这样会造成大量的冗余。但是只用govendor add +指定包又很麻烦。

go mod


go module是Go1.11版本之后官方推出的版本管理工具,并且从Go1.13版本开始,go module将是Go语言默认的依赖管理工具。

包不再保存在GOPATH中,而是被下载到了$GOPATH/pkg/mod路径下.

go mod vendor 会将依赖包放到 vendor 目录

【vendor】Go 包依赖管理工具govendor_github_03

  • go.mod文件记录了项目所有的依赖信息,其结构大致如下:

module github.com/Q1mi/studygo/blogger go 1.12 require ( github.com/DeanThompson/ginpprof v0.0.0-20190408063150-3be636683586 github.com/gin-gonic/gin v1.4.0 github.com/go-sql-driver/mysql v1.4.1 github.com/jmoiron/sqlx v1.2.0 github.com/satori/go.uuid v1.2.0 google.golang.org/appengine v1.6.1 // indirect )


  • go.sum是一个构建状态跟踪文件。它会记录当前module所有的顶层和间接依赖,以及这些依赖的校验和,来确保这些模块的将来下载内容与第一次下载的内容相同,但是第一次下载的模块也有可能是非法的(代理服务不可信、模块源被黑等),所以Go 1.13推出GOSUMDB(Go CheckSum Database)用来公证模块的Hash值,从而提供一个可以100%复现的构建过程并对构建对象提供安全性的保证,同时还会保留过去使用的包的版本信息,以便日后可能的版本回退。

go mod

【vendor】Go 包依赖管理工具govendor_Go_04

go mod 与 go vendor 区别

【vendor】Go 包依赖管理工具govendor_java_05

Golang 管理go类库版本 


【vendor】Go 包依赖管理工具govendor_servlet_06

之前介绍了如何使用github托管go类库,详见​​Golang 使用github托管go类库​​,接着上篇,本篇介绍go类库的版本管理。

Go类库版本规则

go类库版本的规则:​​主版本号.次版本号.修订号​​,其中:

  • 主版本号:类库进行了不可向下兼容的修改,例如功能重构,这时候主版本号往上追加;
  • 次版本号:类库进行了可向下兼容的修改,例如新增功能,这时候次版本号往上追加;
  • 修订号:类库进行了可向下兼容的修改(修改的规模更小),例如修复或优化功能,这时候修订好往上追加。

Go类库发版示例

同样以​​github.com/vsixz/common-go​​类库为示例。

小版本升级

主版本不升级,次版本或修订版本升级。

v0.x.x版本升级至v1.x.x也是可以直接升级的。

当前版本是​​v1.0.0​​​,现对该类库进行了功能修改,发布​​v1.0.1​​版本:

1、切换至release/1.x分支

git checkout release/v1.x

2、修改类库代码

3、提交代码并发布

git add .
git commit -m "update hello"
git push
git tag v1.0.1
git push --tags

4、使用demo-go测试,升级版本

升级类库方式:

  • 使用​​go get -u xxx​​升级至该主版本号下最新版本;
  • 使用​​go get xxx@version​​升级至指定版本。
$ go get - u github.com/vsixz/common-go
go: downloading github.com/vsixz/common-go v1.0.1
go: found github.com/vsixz/common-go/hello in github.com/vsixz/common-go v1.0.1
go: github.com/vsixz/common-go upgrade => v1.0.1

查看​​demo-go​​​下的​​go.mod​​文件,确实升级到了新版本:

【vendor】Go 包依赖管理工具govendor_servlet_07

5、运行测试

$ go run main.go
test hello:
Hello, Jay
common-go version: v1.0.1

大版本升级

主版本升级。

值得注意的是,使用​​go get -u xxx​​升级类库版本时,无法跨主版本升级,只能升级至当前主版本下最新小版本;

v0.x.x 升级至v1.x.x是个例外,可以直接使用​​go get -u xxx​​命令升级。

当前版本是​​v1.0.1​​​,现对该类库进行了功能重构,发布​​v2.0.0​​版本:

1、继续按照最佳实践,创建2.x版本的分支

git checkout -b release/v2.x

2、在类库根目录下创建v2目录,并将当前项目go类库和​go.mod​全拷贝(或剪切)到​v2​目录

【vendor】Go 包依赖管理工具govendor_servlet_08

3、修改module名称至新版

go mod edit -module github.com/vsixz/common-go/v2 v2/go.mod

查看​​v2/go.mod​​文件:

【vendor】Go 包依赖管理工具govendor_servlet_09

修改了module名称后,如果v2目录下的go文件引用本类库的包,需要更新引用v2,否则无法找到引用包。

4、v2类库新增功能

【vendor】Go 包依赖管理工具govendor_Go_10

5、提交代码并发布

git add .
git commit -m "refactor hello to v2"
git push -u origin release/v2.x
git tag v2.0.0
git push --tags

6、使用demo-go测试,升级版本

注意,此时无法通过​​go get -u xxx​​​升级至不同于当前主版本的最新版本,需要使用​​go get xxx@version​​升级:

$ go get github.com/vsixz/common-go/v2@v2.0.0

查看​​go.mod​​​文件,已经添加了​​v2​​版本依赖包

【vendor】Go 包依赖管理工具govendor_Go_11

7、修改测试代码

同时使用​​v1​​​版本和​​v2​​版本的包函数:

【vendor】Go 包依赖管理工具govendor_Go_12

8、运行测试

$ go run main.go
test hello:
Hello, Jay
common-go version: v1.0.1
Hello, Jay Chou
common-go version: v2.0.0

使用本地go类库

如果本地的go类库暂未维护到远端,如何引用本地类库的包呢?

在go.mod文件中使用replace引用本地go类库,这个方式有时候更方便于开发。

common-go的module名称为github.com/vsixz/common-go

replace使用go类库相对路径替换module的引用

以下示例将go类库的引用切换为本地引用。

【vendor】Go 包依赖管理工具govendor_java_13

由于是本地引用,版本号只需在主版本号的范围内即可。

结束语

主版本升级会给代码的维护和版本的维护增加难度,并且需要下游用户迁移版本。最好是当存在令人信服的原因时才对类库主版本进行升级,例如为了优化代码大规模重构。