转载请注明出处:www.huamo.online
Modules概念
一个module是相关Go package的一个集合。modules是源码交互和版本控制的单元。go命令直接支持使用模块,包括记录和解析对其他模块的依赖。modules替代了以前基于GOPATH的方式来指定在构建时使用哪些源文件。
Go 1.11开始初步支持modules这一崭新概念,它统一支持包依赖的版本和路径,版本依赖信息变得轻量而且明确,构建也变得更加可靠和可复现。
module作为一个集合存放在一个以go.mod文件为根的文件树中。go.mod文件定义了模块的module path,这个路径同时也是相对于根目录($GOPATH/src)的import path。还定义了这个模块的依赖需求,即为了完成构建需要用到的其它模块。每一个依赖需求都写作一个模块路径加上一个特定的语义化版本
从Go 1.11开始,如果一个工程目录在 G O P A T H / s r c 外 面 , 且 当 前 目 录 或 任 何 父 目 录 有 g o . m o d 文 件 , 那 么 g o 命 令 就 会 启 用 m o d u l e s ( 如 果 工 程 在 GOPATH/src外面,且当前目录或任何父目录有go.mod文件,那么go命令就会启用modules(如果工程在 GOPATH/src外面,且当前目录或任何父目录有go.mod文件,那么go命令就会启用modules(如果工程在GOPATH/src内部,为了兼容性,go命令依然使用旧的基于GOPATH构建模式,即使找到了go.mod文件)。从Go 1.13开始,module模式会作为所有开发的默认构建模式。
module的初步支持
Go 1.11初步支持modules,包含了一个新的可以感知module的go get命令。开发组会一直保持更新,直到官方宣布正式支持以后,然后就会移除掉GOPATH构建模式以及老的go get命令。
最快最简单的使用新版module构建项目的方式是:将工程目录移到$GOPATH/src外面,并在目录下创建一个go.mod文件,然后在目录下运行go命令。
为了更细粒度的控制,Go 1.11提供了一个临时的环境变量GO111MODULE。可以设置为3个值:off, on, auto(默认值)。如果GO111MODULE=off,那么go命令永不使用module支持,而是像以前一样查看vendor文件夹和 G O P A T H 目 录 来 寻 找 依 赖 ( 这 被 称 为 G O P A T H 模 式 ) 。 如 果 G O 111 M O D U L E = o n , 那 么 g o 命 令 就 会 要 求 使 用 m o d u l e s 特 性 , 而 永 不 再 考 虑 GOPATH目录来寻找依赖(这被称为GOPATH模式)。如果GO111MODULE=on,那么go命令就会要求使用modules特性,而永不再考虑 GOPATH目录来寻找依赖(这被称为GOPATH模式)。如果GO111MODULE=on,那么go命令就会要求使用modules特性,而永不再考虑GOPATH(这被称为module-aware模式)。如果GO111MODULE=auto或未设置,go命令则会依据当前目录来启用或关闭module特性。仅当工程目录在$GOPATH/src外面且本身有go.mod文件或父目录有这个文件,才启用module支持。
在module-aware模式下,构建时 G O P A T H 不 再 定 义 i m p o r t 的 含 义 , 但 它 会 存 储 下 载 好 的 依 赖 ( 存 在 GOPATH不再定义import的含义,但它会存储下载好的依赖(存在 GOPATH不再定义import的含义,但它会存储下载好的依赖(存在GOPATH/pkg/mod),以及安装的可执行命令(一般存在 G O P A T H / b i n , 除 非 系 统 设 置 了 GOPATH/bin,除非系统设置了 GOPATH/bin,除非系统设置了GOBIN)
创建一个新的module
将工程目录创建在$GOPATH/src外面,正常编写代码文件和单元测试代码文件
$ pwd
~/outgopath/gopher/hello
$ ls
hello.go hello_test.go
将工程目录作为module的根目录
$ go mod init gopher/hello
go: creating new go.mod: module gopher/hello
$ pwd
~/outgopath/gopher/hello
$ ls
go.mod hello.go hello_test.go
$ cat go.mod
module gopher/hello
go 1.12
go.mod文件只会出现在module的根目录中。子目录中package的import路径是module路径加上子目录路径即可,且子目录不需要再运行go mod init命令。例如hello/有个子目录world,那么它的import路径就是gopher/hello/world。
添加一个依赖
创造Go modules的主要目的就是为了提高使用其他代码的体验(即添加依赖)
当遇到import了一个go.mod中没有提供的package,go命令就会自动寻找包含这个package的module并将其添加到go.mod中,使用latest版本。所谓的latest规则为:
最新,打了tag标志稳定的版本(非预发行版本),即x.y.z
如果没有,则选最新,打了tag的预发行版本,即x.y.z-abc1
如果还没有,则选最新,没有打tag的版本。
只有直接引用的依赖才记录在go.mod文件中。但是使用go get升级了的依赖,即使是非直接引用,也会记录在go.mod中,下文会说
检查当前模块和它的所有依赖:
$ go list -m all
gopher/hello //主module
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.0
还可以使用go list -m rsc.io…进行模糊搜索
依赖的显示是根据module路径排序
其中golang.org/x/text的是go命令为没有打tag的提交生成的伪版本
go命令还维护了一个go.sum文件,包含了每个依赖的加密哈希校验和。以此确保以后的下载依赖和初次下载的内容完全一致。
go.mod和go.sum都需要检入到版本控制中。
升级依赖
可以使用go get -v golang.org/x/text升级这个依赖,这里没有指定升级到的版本,就会默认升级到@latest。完成之后,go.mod就会新增记录,go.sum也会随之更新。即使是非直接依赖,此时也会记录在go.mod中
也可以使用go get -v rsc.io/sampler@v1.3.1指定升级版本。
$ go get -v rsc.io/sampler@v1.3.1
$ go get -v golang.org/x/text
$ cat go.mod
module gopher/hello
go 1.12
require (
golang.org/x/text v0.3.0 // indirect
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.1 // indirect
)
增加一个新的主版本依赖
就像以太坊中遇到的那样,whisper有v5和v6两个版本,分别对应两个目录,现在我终于明白了为什么会这样分开冗余代码,因为主版本的变更一般都是对外接口不再向后兼容,但是对于一个已经存在的module,别人有可能还在依赖旧版本代码,所以只能以主版本号为文件夹名开辟新的module path,这种惯例称为语义化导入版本
所以,在go import中,可以同时依赖一个模块的多个主版本,例如:
$ vim hell.go
…
import (
“rsc.io/quote”
quoteV3 “rsc.io/quote/v3”
)
…
$ go list -m rsc.io/q…
rsc.io/quote v1.5.2
rsc.io/quote/v3 v3.1.0
这样就可以既使用部分新特性,又能和老版本进行兼容。
移除未使用的依赖
go build或者go test这种命令可以快速发现缺少了什么,但并不能安全的告知什么可以移除,因为移除一个依赖需要在检查完这个module下所有的包之后才能做,包括这些包的所有可能编译参数组合都检查通过才行。
go mod tidy可以完成这个使命
Go包版本提议
介绍
8年前,Go开发组推出了goinstall(最后演化为go get),其去中心化,类似URL的导入路径对Go开发者颇为熟悉。当goinstall发布之后,人们最先询问的问题便是如何纳入版本信息。Go开发组承认:We admitted we didn’t know。长期以来,他们都认为包版本的问题最好是通过一个插件工具来解决,他们也鼓励社区创造出一个这样的工具。于是很多工具用了很多不同方式来解决这个问题,到了2016中间的时候,市面上已经出现了太多解决方案,开发组认为需要选用一个单一的,官方的工具结束这个局面。
参考链接
https://golang.org/cmd/go/#hdr-Modules__module_versions__and_more
https://golang.org/doc/go1.11#modules
https://blog.golang.org/versioning-proposal
语义化版本:https://semver.org/lang/zh-CN/
https://blog.golang.org/using-go-modules
https://golang.org/cmd/go/#hdr-Preliminary_module_support
https://golang.org/cmd/go/#hdr-Pseudo_versions
https://golang.org/cmd/go/#hdr-Module_downloading_and_verification
https://research.swtch.com/vgo-import
转载请注明出处:www.huamo.online