Go Modules 是 golang 1.11 才新增加的一个特性,虽然还处于试验阶段,不过官方说明中表示后续的版本会持续保持对已发布功能的兼容,所以我们还是可以大胆地进行尝试……
快速上手
在 $GOPATH 路径之外创建一个目录,并初始化一个新的 module:
这样子就会生成一个 go.mod 文件,然后我们再写一段简单的代码:
执行 go build,生成可执行文件 hello,以及 go.sum 文件:
查看 go.mod 和 go.sum 文件的内容,可以发现其中包含了依赖的包:
当我们执行 go build 或者 go get 命令时,项目所需要的依赖将会自动下载到 $GOPATH/pkg/mod/ 目录下(作为缓存,可被其他项目依赖使用),并更新 go.mod 和 go.sum。
当然,我们还可以指定特定的版本或者分支比如: go get foo@1.2.3 或 go get foo@master。此外,还有一些常用的命令:
- go list -m all:列出所有依赖的最终版本
- go list -u -m all:列出可更新的依赖
- go get -u:更新依赖
- go build ./… 或 go test ./… :在项目根目录下执行,构建/测试 module 中 的包
- go mod download:下载依赖到本地缓存
- go mod tidy:增加需要的依赖,删除不需要的依赖
- go mod vendor:把依赖复制到项目的 vendor 目录
基本概念
Modules
A module is a collection of related Go packages that are versioned together as a single unit.
- 一个 repository 包含一个或多个 Go modules;
- 每个 module 包含一个或多个 Go packages;
- 每个 package 由单一目录下的一个或多个 Go 源文件 组成;
go.mod
一个 Module 由位于根目录的 go.mod 和一些 go 文件构成,module 可以放在 $GOPATH 目录之外。
如何使用
初始化
首先,需要安装 Go 1.11 以上版本,然后:
- 在 $GOPATH/src 目录外,直接执行 go 命令(环境变量GO111MODULE无需设置,或设置为 auto);
- 在 $GOPATH/src 目录下,设置 GO111MODULE=on,再执行 go 命令;
如果是在 $GOPATH/src 目录下,执行 go mod init 将会自动确定 module 的名字,不然就需要输入 module 名字 go mod init moduleName。
更新/回退
使用 go get 命令:
- 执行 go get -u 更新最新版本(到 minor 或者 patch 版本)
- 为指定的包选择指定的版本:
- go get foo 相当于 go get foo@latest
- go get foo@1.2.3
- go get foo@e3702bed2
- go get foo@'<1.6.2′
发布
大部分的步骤将会被未来的 go release 工具自动化执行,不过目前我们可以这么操作:
- 执行 go mod tidy 移除不必要的依赖,因为 go build/test 并不会自动删除不再需要的依赖;
- 执行 go test all 测试;
- 把 go.sum 和 go.mod 加入到 vcs 中提交;
Vendor
前面我们提到了,如果启用了 Modules ($GOPATH/src 外或 GO111MODULE=on),默认的依赖都是下载到 $GOPATH/pkg/mod 目录下,我们也可以使用 go mod vendor 将依赖添加到项目根目录的 vendor 目录中。
不过,此时如果我们直接执行 go build 命令,那么使用仍然是 go.mod 描述的依赖( $GOPATH/pkg/mod )而非 vendor 中的依赖,我们需要指定 -mod=vendor 参数:
这样子 go 命令就可以忽略了 go.mod,而认为 vendor 目录包含了正确的依赖。
另外,如果指定了 -mod=readonly 参数,则 go build 过程中 go.mod 将不会被自动更新(如果 go.mod 需要被修改,那么构建就是失败)。这个参数常用于 CI 自动化构建,保证正确的依赖关系。
最后,注意 -mod 构建参数只对 go build 有效,而 go test 会将其忽略。
参考:
- https://github.com/golang/go/wiki/Modules
- https://roberto.selbach.ca/intro-to-go-modules/
- https://www.youtube.com/watch?v=F8nrpe0XWRg&list=PLq2Nv-Sh8EbbIjQgDzapOFeVfv5bGOoPE&index=3&t=0s
跳出Go module的泥潭
说明: go module增在快速的成长中,最近每个版本中(1.11 ~ 1.13)都有很大的变动。 建议你阅读官方的wiki了解go module最新的知识: go/wiki/Modules
最新扩展阅读(go 1.13):Go module 再回顾。
Go 1.11 前天已经正式发布了,这个版本包含了两个最重要的feature就是 module和web assembly。虽然也有一些简单的教程介绍了go module的特性,但是基本上都是hello world的例子,在实践的过程中, 很多人都在“拼命的挣扎”,包括我自己, 从一些qq群、github的issue, twitter上都可以看到大家茫然或者抱怨的语句。
虽然有三个帮助文件go help mod、go help modules、go help module-get可以了解一些go module的用法,但是感觉Go开发组对module这一特性还是没有很好的做一个全面的介绍,很多情况还得靠大家看源代码或者去猜,比如module下载的文件夹、版本格式的完整声明,module的最佳实践等,并且当前Go 1.11的实现中还有一些bug,给大家在使用的过程中带来了很大的困难。
我也在摸索中前行, 记录了摸索过程中的一些总结,希望能给还在挣扎中的Gopher一些帮助。
Introduction to Go Modules 是一篇很好的go module 入门介绍, 如果你仔细阅读了它,应该就不需要看本文了。
GO111MODULE
要使用go module,首先要设置GO111MODULE=on,这没什么可说的,如果没设置,执行命令的时候会有提示,这个大家应该都了解了。
既有项目
假设你已经有了一个go 项目, 比如在$GOPATH/github.com/smallnest/rpcx下, 你可以使用go mod init github.com/smallnest/rpcx在这个文件夹下创建一个空的go.mod (只有第一行 module github.com/smallnest/rpcx)。
然后你可以通过 go get ./...让它查找依赖,并记录在go.mod文件中(你还可以指定 -tags,这样可以把tags的依赖都查找到)。
通过go mod tidy也可以用来为go.mod增加丢失的依赖,删除不需要的依赖,但是我不确定它怎么处理tags。
执行上面的命令会把go.mod的latest版本换成实际的最新的版本,并且会生成一个go.sum记录每个依赖库的版本和哈希值。
新的项目
你可以在GOPATH之外创建新的项目。
go mod init packagename可以创建一个空的go.mod,然后你可以在其中增加require github.com/smallnest/rpcx latest依赖,或者像上面一样让go自动发现和维护。
go mod download可以下载所需要的依赖,但是依赖并不是下载到$GOPATH中,而是$GOPATH/pkg/mod中,多个项目可以共享缓存的module。
go mod命令
|
|
有些命令还有bug, 比如go mod download -dir:
|
|
帮助里明明说可以设置dir,但是实际却不支持dir参数。
看这些命令的帮助已经比较容易了解命令的功能。
翻墙
在国内访问golang.org/x的各个包都需要翻墙,你可以在go.mod中使用replace替换成github上对应的库。
|
|
依赖库中的replace对你的主go.mod不起作用,比如github.com/smallnest/rpcx的go.mod已经增加了replace,但是你的go.mod虽然require了rpcx的库,但是没有设置replace的话, go get还是会访问golang.org/x。
所以如果想编译那个项目,就在哪个项目中增加replace。
版本格式
下面的版本都是合法的:
|
|
go get 升级
- 运行
go get -u将会升级到最新的次要版本或者修订版本(x.y.z, z是修订版本号, y是次要版本号) - 运行
go get -u=patch将会升级到最新的修订版本 - 运行
go get package@version将会升级到指定的版本号version
go mod vendor
go mod vendor 会复制modules下载到vendor中, 貌似只会下载你代码中引用的库,而不是go.mod中定义全部的module。
go module, vendor 和 Travis CI
https://arslan.io/2018/08/26/using-go-modules-with-vendor-support-on-travis-ci/
from https://colobu.com/2018/08/27/learn-go-module/
No comments:
Post a Comment