eplace暂时没有什么用处,当然以后如果有变动的话说不定可以发挥比现在更大的作用。
发布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目录。
接下来使用go build -mod=vendor
来构建项目,因为在go modules模式下go build是屏蔽vendor机制的,所以需要特定参数重新开启vendor机制:
go build -mod=vendor
./my-module
a notify!
构建成功。当发布时也只需要和使用godep时一样将vendor目录带上即可。
注意包版本
其实这是第一部分的老生常谈,当你发布一个v2+版本的库时,需要进行以下操作:
- 将
module my-module
改成module my-module/v2
- 将源代码中使用了v2+版本包的import语句从
import "my-module"
改为import "my-module/v2"
- 仔细检查你的代码中所有
my-module
包的版本是否统一,修改那些不兼容的问题
- 在changelog中仔细列出所有breaking changes
- 当然,如果你觉得前面四步过于繁琐,注明你的用户需要指定
+incompatible
是一个暂时性的解决方案。
注意以上几点的话发布go modules也就是一个轻松的工作了。
小结
相比godep和vendor机制而言,go modules已经是向现代包管理器迈出的坚实一步,虽然还有不少僵硬甚至诡异的地方,但是个人还是推荐在go1.12发布后考虑逐步迁移到go modules,毕竟有官方的支持,相关issues的讨论也很活跃,不出意外应该是go包管理方案的最终答案,现在花上一些时间是值得的。
当然包管理是一个很大的话题,就算本文也只是讲解了其中的一二,以后我也许有时间会介绍更多go modules相关的内容。
总之go modules还是一个新兴事物,包管理器是一个需要不断在实践中完善的工具,如果你有建设性的想法请尽量向官方反馈。
go modules的官方wiki也上线一段时间了,这篇文件基本上是与其结合的查漏补缺,同时也夹杂了一些个人见解,所以难免有所错误疏漏,欢迎指正。
参考
go modules wiki