type
status
date
slug
summary
tags
category
icon
password
Sub-item
Last edited time
Oct 29, 2023 12:42 AM
Parent item
领域
go的包通过module管理,module 代表一个版本管理单元,它包括一个或者多个 packages。
生成依赖包清单
go项目通过go mod命令管理当前项目依赖包
在项目目录下执行下面的命令,会生成项目的依赖包管理文件go.mod
注意:如果是需要打包成模块被别人使用, 那么模块名称带上路径,你如:
github.com/shiqinfeng1/xxx
,如果是项目代码,可以使用当前文件夹名称,一般也是项目名称,作为模块名称。然后自动生成项目依赖的第三方包的列表清单:
执行后文件go.mod的内容类似如下:
注意每个依赖包后面会带一个版本号,默认情况下会使用依赖包最新版本,如果需要使用指定的版本号, 那么可以手动修改为指定的版本号。
管理依赖包版本
发布包的版本规范
go的包版本需要满足semver语义化版本规范。
举个例子,比如你开发了一个 module (github.com/you/foo) 提供给用户使用,最初的时候你给这个 module 打了一个版本为 v1.0.0。并且直到 v1.5.9 为止没有出现过不能向前兼容的情况。
但现在,你要发布一个全新的版本,从而不能向前兼容。所以 semver 规则,你需要将版本号定义成 v2.0.0。
具体更新:
- 修改go.mod,module后面加v2:
module github.com/shiqinfeng1/xxx/v2
- 打标签:
也可以新建一个v2分支,在v2分支上打tag:
git checkout -b v2
依赖包兼容版本管理
如果有 3 个包, 分别为 foo1, foo2, foo3。 foo1 依赖 foo3@v1.0.1, foo2 依赖 foo3@v1.0.2。 现在我们需要实现一个功能,需要同时使用 foo1 和 foo2 两个包, 那我们应该使用什么版本的 foo3 呢?对于这种情况,在 foo1 的根目录下, 有一个 go.mod 文件, 包括一行依赖信息;
require foo3 v1.0.1
。 在 foo2 的根目录下, 有一个 go.mod 文件, 包括一行依赖信息; require foo3 v1.0.2
。在编译我们自己的 module bar 时, 会使用哪个版本的 foo3 呢? 答案是 v1.0.2。将 golang 选择 foo3 的版本的算法叫做 最小版本选择算法。
它选出来的版本是所有 go.mod 文件(在这里包括 foo1, foo2 和 bar 下的 go.mod 文件) 中明确指定的最大版本。
这里的最小的意思是 foo1 和 foo2 给出的依赖的版本都是最小化了的, 比如 foo1 依赖 foo3@v1.0.1, 那么根据 semver 规则, foo1 在 foo3@v1.0.2 下也可以正常工作, 因为 foo3@v1.0.2 是向前兼容了 foo3@v1.0.1 的。
依赖包的不兼容版本管理(v1→v2)
上述例子中,如果 foo2 依赖的是 foo3@v2.1.1, 我们编译 bar 时,会使用哪个版本的 foo3 呢? 答案是:v1.0.1 和 v2.1.1 。
根据导入兼容规则, v1.0.1 和 v2.1.1 使用的是不同的路径,一个是 v1.0.1 使用的是 foo3,而 v2.1.1 使用的是 foo3/v2。 所以可以同时存在于一次编译中。 而且 v2.1.1 是不能兼容 v1.0.1 的,所以 foo1 没法使用 v2.1.1 版本,因此也必须同时使用 foo3 的两个版本。
注意,导入兼容规则 规定,如果你的新版本不能向老版本兼容,你必须在import时修改包路径为 github.com/xxx/xxx/v2,然后再执行
go mod tidy
后,在go.mod中的包路径会自动带上/v2, 并在tag的主版本号为2的tag中匹配最新版本(或手动指定v2下的其他版本)。依赖包的伪版本号
如果一个 module 没有有效的 semver 版本,那么 go.mod 将通过一个叫做 “伪版本“ 的东西来记录版本。
”伪版本“ 的通常形式是 vX.0.0-yyyymmddhhmmss-abcdefabcdef。 比如
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
其中 v0.0.0 表示 semver 版本号, 20170915032832 表示这个版本的时间。 14c0d48ead0c 表示这次提交的 hash。
依赖包次版本升级
- 运行go get -u 将会升级到最新的次要版本或者修订版本(x.y.z, z是修订版本号, y是次要版本号)
- 运行 go get -u=patch 将会升级到最新的修订版本
分叉第三方包后修改代码,整体repalce原第三方包的路径
由于项目中会在很多文件中import该第三方包,分叉后修改代码,变成一个新的第三方包地址,此时如果需要使用新的包地址,有2种方式:
- 全局替换import 路径,把原第三方包路径换成新的路径。这种方式改动多,容易出错。
- 使用replace,在go.mod中重定向包的路径。推荐使用这种方式。
修改方法:
在当前项目中,执行
go mod edit -replace
命令:执行完命令后,我们打开
go.mod
文件,发现最下面多了一条指令: