You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
D:\Code\go>go test
PASS
ok _/D_/Code/go 0.327s
D:\Code\go>
最后一行总结了整体包测试。 因为我们在$GOPATH之外以及任何模块之外工作,所以go命令不知道当前目录的导入路径,并根据目录名称构成假路径:_/D_/Code/go。
现在,我们在当前目录下执行go mod init,然后再进行go test:
D:\Code\go>go mod init example.com/hello
go: creating new go.mod: module example.com/hello
D:\Code\go>go test
PASS
ok example.com/hello 0.393s
D:\Code\go>
恭喜!你已经写了一个模块,并且通过了测试 go mod init命令生成一个go.mod文件:
PS D:\Code\go> cat .\go.mod module example.com/hello
go 1.12
PS D:\Code\go>
go.mod文件只会出现再模块的根目录,子目录中的包具有导入路径,包括模块路径和子目录的路径。例如,我们创建一个子目录world,我们可以不在再次执行go mod init,包会自动加载并且可以被识别出是example.com/hello的一部分,导入路径就是example.com/hello/world。
D:\Code\go>type go.mod
module example.com/hello
go 1.12
require rsc.io/quote v1.5.2
D:\Code\go>
再一次执行go test的时候,就不会重复上一次的任务了,因为go.mod现在已经更新了,并且依赖已经被缓存到了本地($GOPATH/pkg/mod)
正如我们看到的,添加一个依赖经常会带来其他的依赖,go list -m命令可以列出当前模块的所有依赖
yankeweideMacBook-Pro:hello yankewei$ go list -m all
hello
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.0
yankeweideMacBook-Pro:hello yankewei$
在Go模块中,版本使用语义化的标记来表示的。一个语义化的版本有三个部分:主版本,次要版本,修补版本。例如:对于 v0.1.2,主版本号是0,次要版本是1,修补版本是2。
执行go list -m all 会看到golang.org/x/text是没有标签的版本。现在来把它更新到最新版本,并且测试一下看是否可以正常工作:
$ go get golang.org/x/text
go: finding golang.org/x/text v0.3.0
go: downloading golang.org/x/text v0.3.0
go: extracting golang.org/x/text v0.3.0
$ go test
PASS
ok example.com/hello 0.013s
$
很好!测试通过,再执行go list -m all,并且看一下go.mod文件的内容:
$ go list -m all
example.com/hello
golang.org/x/text v0.3.0
rsc.io/quote v1.5.2
rsc.io/sampler v1.3.0
$ cat go.mod
module example.com/hello
go 1.12
require (
golang.org/x/text v0.3.0 // indirect
rsc.io/quote v1.5.2
)
$
golang.org/x/test包已经被更新到了最新的版本(v0.3.0)。indirect注释表示依赖没有被这个模块直接使用,仅仅被其他的模块间接使用,可以通过go help modules查看相信信息。
现在让我们尝试更新rsc.io/sampler版本。
$ go get rsc.io/sampler
go: finding rsc.io/sampler v1.99.99
go: downloading rsc.io/sampler v1.99.99
go: extracting rsc.io/sampler v1.99.99
$ go test
--- FAIL: TestHello (0.00s)
hello_test.go:8: Hello() = "99 bottles of beer on the wall, 99 bottles of beer, ...", want "Hello, world."
FAIL
exit status 1
FAIL example.com/hello 0.014s
$
糟糕!测试失败了,最新的版本和我们要使用的不兼容,先看一下这个模块的可用版本:
$ go list -m -versions rsc.io/sampler
rsc.io/sampler v1.0.0 v1.2.0 v1.2.1 v1.3.0 v1.3.1 v1.99.99
$
我们已经使用过v1.3.0;v1.99.99版本不兼容,可以尝试使用v1.3.1:
$ go get rsc.io/[email protected]
go: finding rsc.io/sampler v1.3.1
go: downloading rsc.io/sampler v1.3.1
go: extracting rsc.io/sampler v1.3.1
$ go test
PASS
ok example.com/hello 0.022s
$
简介
Go 1.11 和 1.12 都对模块有了初步的支持,使得对依赖的管理更加详细和容易。这个文章对模块的使用做一个基本的介绍。
模块是对Go包一个集合,以一个文件树的形式存储在根目录的
go.mod
文件中。go.mod
文件定义了模块的路径,还有相关的依赖项。每一个依赖项都会被认为是一个模块路径和指定的版本规则,其实就是依赖项也是一个模块。在Go 1.11的时候,Go命令行就有了对模块的支持,当当前的目录或者父目录有
go.mod
文件的时候,并且可以在GOPATH
以外的地方使用,为了兼容性,即使在GOPATH
中发现了go.mod
文件,也会使用GOPATH
的方式来加载文件。从Go 1.13开始,模块将被默认支持。本文将介绍使用模块开发Go代码时出现的一系列常见操作:
创建一个模块
让我们来创建一个模块。
在
$GOPATH/src
目录之外创建一个新的,空的目录,进入目录然后创建一个新文件hello.go
,在
hello_test.go
文件中写一个测试这是,当前目录中包含了一个包,并不是一个模块,因为这里还没有
go.mod
文件,如果我们在当前目录下执行go test
,可以看到:最后一行总结了整体包测试。 因为我们在
$GOPATH
之外以及任何模块之外工作,所以go命令不知道当前目录的导入路径,并根据目录名称构成假路径:_/D_/Code/go
。现在,我们在当前目录下执行
go mod init
,然后再进行go test
:恭喜!你已经写了一个模块,并且通过了测试
go mod init
命令生成一个go.mod
文件:go.mod
文件只会出现再模块的根目录,子目录中的包具有导入路径,包括模块路径和子目录的路径。例如,我们创建一个子目录world
,我们可以不在再次执行go mod init
,包会自动加载并且可以被识别出是example.com/hello
的一部分,导入路径就是example.com/hello/world
。添加一项依赖
Go模块的主要作用是提升可以使用其他开发人员提供的代码。
更新
hello.go
,导入rsc.io/quote
包:再一次执行
go test
go命令会解析
go.mod
文件中指定的依赖和版本。当遇见一个在go.mod
中没有提供的包时,go命令会自动查找这个包并且添加到go.mod
文件中,使用最新的版本(最新的版本指的时被打标签的稳定版,或者最新的预发布版本,或者最新的版本),在我们这个例子中,go test
解析了一个新的包rsc.io/quote
,版本为v1.5.2。还下载了两个包rsc.io/quote
使用的两个依赖项,就是rsc.io/sampler
和golang.org/x/test
。go.mod
文件指记录直接的依赖关系:再一次执行
go test
的时候,就不会重复上一次的任务了,因为go.mod
现在已经更新了,并且依赖已经被缓存到了本地($GOPATH/pkg/mod)正如我们看到的,添加一个依赖经常会带来其他的依赖,
go list -m
命令可以列出当前模块的所有依赖在输出的内容中,当前的模块名总是会出现在第一行,紧跟着按依赖的模块路径排序。
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
是一个伪版本号,这个go系统对于一个没有打标的commit的标识。除了go.mod之外,go命令还维护一个名为go.sum的文件,其中包含特定模块版本内容的预期加密哈希:
go使用go.sum文件来确保未来下载这些模块的时候保证和第一次下载的一样,也确保你项目的依赖不会改变,所以go.mod和go.sum都应该纳入版本控制中。
更新依赖
在Go模块中,版本使用语义化的标记来表示的。一个语义化的版本有三个部分:主版本,次要版本,修补版本。例如:对于 v0.1.2,主版本号是0,次要版本是1,修补版本是2。
执行
go list -m all
会看到golang.org/x/text
是没有标签的版本。现在来把它更新到最新版本,并且测试一下看是否可以正常工作:很好!测试通过,再执行
go list -m all
,并且看一下go.mod文件的内容:golang.org/x/test
包已经被更新到了最新的版本(v0.3.0)。indirect
注释表示依赖没有被这个模块直接使用,仅仅被其他的模块间接使用,可以通过go help modules
查看相信信息。现在让我们尝试更新
rsc.io/sampler
版本。糟糕!测试失败了,最新的版本和我们要使用的不兼容,先看一下这个模块的可用版本:
我们已经使用过v1.3.0;v1.99.99版本不兼容,可以尝试使用v1.3.1:
我们在
go get
的参数中指定@v1.3.1
。默认是@latest
,也就是最新的版本添加一个新的主版本
我们添加一个新的函数
func Proverb
, 函数会调用rsc.io/quote/v3
的模块,在这个模块中可以调用quote.Concurrency
,返回一个字符串,首次我们先来更新hello.go文件:然后在hello_test.go添加一个测试:
现在可以执行代码:
现在我们的项目有两个依赖
rsc.io/quote
和rsc.io/quote/v3
每个不同的主版本(v1,v2等等)的模块使用的是不同的路径,这样就可以选择性的使用,并且在版本迁移的时候也可以逐步的进行。
更新依赖为新的主版本
现在我们想要把
rsc.io/quote
更新到rsc.io/quote/v3
。因为主版本号已经变了,我们可能会意识到某些api被移除,被重命名或者调用方法发生了改变,所以首先我们需要先看一下文档:可以看到原来的 Hello 改为了 HelloV3,那我们就可以把使用的 Hello 改为 HelloV3,并且文件中没有对旧版本的依赖了,可以把导入重命名去掉:
可以自行测试,就不演示了。
删除未使用的依赖
在Go语言中删除未使用的依赖相当的简单,只需要执行
go mod tidy
。原文链接
The text was updated successfully, but these errors were encountered: