再探go modules:使用与细节 (3)

间接依赖是指在当前module中没有直接import,而被当前module使用的第三方module引入的包,相对的顶层依赖就是在当前module中被直接import的包。如果二者规则发生冲突,那么顶层依赖的规则覆盖间接依赖。

在这里golang.org/x/net被github.com/chromedp/chromedp引入,但当前项目未直接import,所以是一个间接依赖,而github.com/chromedp/chromedp被直接引入和使用,所以它是一个顶层依赖。

而我们的replace命令只能管理顶层依赖,所以在这里你使用replace golang.org/x/net => github.com/golang/net是没用的,这就是为什么会出现go build时仍然去下载golang.org/x/net的原因。

那么如果我把// indirect去掉了,那么不就变成顶层依赖了吗?答案当然是不行。不管是直接编辑还是go mod edit修改,我们为go.mod添加的信息都只是对go mod的一种提示而已,当运行go build或是go mod tidy时golang会自动更新go.mod导致某些修改无效,简单来说一个包是顶层依赖还是间接依赖,取决于它在本module中是否被直接import,而不是在go.mod文件中是否包含// indirect注释。

限制

replace唯一的限制是它只能处理顶层依赖。

这样限制的原因也很好理解,因为对于包进行替换后,通常不能保证兼容性,对于一些使用了这个包的第三方module来说可能意味着潜在的缺陷,而允许顶层依赖的替换则意味着你对自己的项目有充足的自信不会因为replace引入问题,是可控的。相当符合golang的工程性原则。

也正如此replace的适用范围受到了相当的限制:

可以使用本地包替换将生成代码纳入go modules的管理

对于直接import的顶层依赖,可以替换不能正常访问的包或是过时的包

go modules下import不再支持使用相对路径导入包,例如import "./mypkg",所以需要考虑replace

除此之外的replace暂时没有什么用处,当然以后如果有变动的话说不定可以发挥比现在更大的作用。

发布go modules
本部分将讨论如何发布你的modules到github等开源仓库以供他人使用,放心这是相对来说最轻松的一部分。

go.sum不是锁文件

也许你知道npm的package-lock.json的作用,它会记录所有库的准确版本,来源以及校验和,从而帮助开发者使用正确版本的包。通常我们发布时不会带上它,因为package.json已经够用,而package-lock.json的内容过于详细反而会对版本控制以及变更记录等带来负面影响。

如果看到go.sum文件的话,也许你会觉得它和package-lock.json一样也是一个锁文件,那就大错特错了。go.sum不是锁文件。

更准确地来说,go.sum是一个构建状态跟踪文件。它会记录当前module所有的顶层和间接依赖,以及这些依赖的校验和,从而提供一个可以100%复现的构建过程并对构建对象提供安全性的保证。

go.sum同时还会保留过去使用的包的版本信息,以便日后可能的版本回退,这一点也与普通的锁文件不同。所以go.sum并不是包管理器的锁文件。

因此我们应该把go.sum和go.mod一同添加进版本控制工具的跟踪列表,同时需要随着你的模块一起发布。如果你发布的模块中不包含此文件,使用者在构建时会报错,同时还可能出现安全风险(go.sum提供了安全性的校验)。

使用vendor目录

golang一直提供了工具选择上的自由性,如果你不喜欢go mod的缓存方式,你可以使用go mod vendor回到godep或govendor使用的vendor目录进行包管理的方式。

当然这个命令并不能让你从godep之类的工具迁移到go modules,它只是单纯地把go.sum中的所有依赖下载到vendor目录里,如果你用它迁移godep你会发现vendor目录里的包回合godep指定的产生相当大的差异,所以请务必不要这样做。

我们举第一部分中用到的项目做例子,使用go mod vendor之后项目结构是这样的:

tree my-module my-module ├── go.mod ├── go.sum ├── main.go └── vendor ├── github.com │   ├── mattn │   │   └── go-gtk │   │   └── glib │   │   ├── glib.go │   │   └── glib.go.h │   └── mqu │   └── go-notify │   ├── LICENSE │   ├── README │   └── notify.go └── modules.txt

可以看到依赖被放入了vendor目录。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyjydj.html