摘要:很显然,Go开发者要强推go module功能了,但是如果你不了解的这种变化的化,很可能变得很茫然,因为初次使用go module可能会重新下载很多的依赖库。不客气地的说,go module的实现不是一个很成功的功能的添加,首先go module的引入就引入了很大的争议,包括dep等多个go依赖工具的作者颇有微词,其次go module的功能并没有很好的设计就开始引入到go的发布版本中,导致Go多个版本module功能在不停的修修补补,第三,虽然go module也一些官方的文档,但是文档并不详细,也没有很好的列出各个版本对相应工具的影响。

我曾经写了一篇跳出Go module的泥潭, 记录了使用go module的一些坑,随着Go 1.13版本的发布,go module的功能再不断的演化(或者不委婉的说在不断的修补),go module很多功能也发生了变化,这篇文章记录了新版本( go 1.13 )下module的使用方法。

不客气地的说,go module的实现不是一个很成功的功能的添加,首先go module的引入就引入了很大的争议,包括dep等多个go依赖工具的作者颇有微词,其次go module的功能并没有很好的设计就开始引入到go的发布版本中,导致Go多个版本module功能在不停的修修补补,第三,虽然go module也一些官方的文档,但是文档并不详细,也没有很好的列出各个版本对相应工具的影响。另外,go module多个版本的实现导致一些工具比如go等不向下兼容,刚入的新的Go开发者感觉不到兼容的变化,但是老的go开发者就很痛苦了,因为执行相同的命令产生了不同的"执行语义"。

如著名的Go布道者 Bill Kennedy 的吐槽:

当然,go module设计初衷还是好的,而且go生态圈也应该有一个强势的库依赖工具避免分片化。

即使你对go module有一件,我的观点是如果你不能改变它,那么就去接收它,所以让我们来了解一下go module对现有的功能的影响。

环境变量

首先, GO111MODULE 环境变量并没有被移除,它的默认值也没有发生了改变,依然是在auto, 但是auto的含义却发生了变化 :(。

在Go 1.13中auto意味着当前目录或者在目录中包含 go.mod 文件夹的话,即使当前目前在 $GOPATH/src 下,也会开启module模式。

很显然,Go开发者要强推go module功能了,但是如果你不了解的这种变化的化,很可能变得很茫然,因为初次使用go module可能会重新下载很多的依赖库。

相应的,这也对常用的IDE产生影响,幸运地是,主流的IDE都支持了go module功能,不用担心引入的库找不到的问题。

GOPROXY 环境变量设置代理服务器,可以设置多个代理服务器以及direct,已经有很多的代理服务器了,不用担心墙的问题,比如 https://goproxy.cn,direct

GOSUMDB 可以用来校验你下载的库的哈希是否和官方的哈希值是否一样,避免被proxy给修改了,玩意proxy给你的下载库加上挖矿代码就惨了,毫无疑问也被墙了,即使专为中国区设置的域名/服务器也被墙。你可以使用 goproxy.cn 作为GOSUMDB服务器,或者心大使用 GOSUMDB=off 进行禁用。

GOPRIVATE 用来设置不使用代理的仓库,比如一些公司内部的仓库等等,如 GOPRIVATE=*.corp.example.com,rsc.io/private

作为和以前的兼容,还保留着 GONOPROXY ,功能和 GOPRIVATE 一样。

go env -w 可以为这些值设置为全局变量。有些人不建议你这么做,因为可能你在你的开发环境中编译好好的,但是在服务器或者docker中项目却无法编译,所以建议将这些环境变量写到配置文件如Makefile中。

go help module-auth 了解 GOSUMDBGONOSUMDB 变量。

go help goproxy 了解proxy的通讯协议。

go help modules 了解module的功能。

go help module-get 了解 go get 命令的变化。而 go help gopath-get 显示先前的基于GOPATH的go get功能。

go help module-private 了解私有库的设置。

go mod 命令

go help mod 显示 go mod 命令的子命令:

$GOPAH/pkg/mod
go help mod why

一般新的项目,无论文件夹在哪里,首先 go mod init 初始化它,然后 go mod tidy 自动将引入的库加入到go.mod文件中。

go action 工具

老司机比较不适应的使用 go xxxx 工具参数和语义的改变。

如何更新go.mod文件中的库的版本到最新版本?如何值更新当前项目?如何更新本地库和依赖库?

go get

当前go get的命令的格式是 go get [-d] [-t] [-u] [-v] [-insecure] [build flags] [packages]

首先 go get 会寻找依赖库的版本,它会寻找库的最新的tag未release的版本(tagged release version), 如 v0.4.5v1.2.3 , 如果没有,则寻找pre版,如 v0.0.1-pre1 ,如果都没有,寻找最新的commit版。

当然你也可以指定下载某个库的某个特定的版本,如 go get golang.org/x/[email protected]go get golang.org/x/text@master

-t 是也下载 test 文件中的依赖。

-u 指示下载的库使用最新的 minorpatch 最新版。'go get -u A'下载最新的A, 以及A依赖的 B v1.3.1 (而不是 B v1.2.3)。假如B依赖C,而C并没有提供任何A所需的包,那么C不会更新。

-u=patch 更新pacth release。'go get -u=patch A@latest'更新A到最新版,依赖的B更新到v1.2.4(而不是 V1.3.1)。

go get -u=patch A 把A更新到最新的patch版,而不是minor版。

go get xxxxx/... 可以批量安装工具。 go get golang.org/x/perf/cmd/... 会安装perf的所有的命令行工具到 $GOPATH/bin 中。

go get 相当于 go get . ,它应用于当前文件夹对应的包, go get -ugo get -u=patch 同样的处理。

没有 -u 的时候, go get 并不会比 go install 多做什么, go get -d 也不会比 go list 多做什么。

go list

go list 列出所依赖的库,格式如下:

go list [-f format] [-json] [-m] [list flags] [build flags] [packages]

-f 指定要显示的字段, -json 指定显示的格式为json格式,否则为每行一条记录的方式。

比如:

# go list ./...
github.com/smallnest/rpcx/client
github.com/smallnest/rpcx/codec
github.com/smallnest/rpcx/errors
github.com/smallnest/rpcx/log
github.com/smallnest/rpcx/protocol
github.com/smallnest/rpcx/server
github.com/smallnest/rpcx/serverplugin
github.com/smallnest/rpcx/share
github.com/smallnest/rpcx/tool/xgen
github.com/smallnest/rpcx/tool/xgen/parser
github.com/smallnest/rpcx/util

或者 go list -f '\{\{.ImportPath\}\}' ./...go list -json ./...

-deps 还会列出它们的依赖。

它还有其它一些参数,比如 -e-compiled-test , 还有 -m 参数。

-m 列出所依赖的module,而不是package,比如 go list -m all

-u 可以列出可升级的库的信息,如 go list -m -u -json all

-versions 显示库的可用的版本列表。

all

all 现在是go action中一个特殊的语义,代表main module和它的依赖( The special pattern "all" specifies all the active modules, first the main module and then dependencies sorted by module path.

... 代表代表匹配这个模式的所有活动的module( A pattern containing "..." specifies the active modules whose module paths match the pattern. )

go get allgo list allgo get -u allgo get ./...go get -u ./... 都是合法的。

go保留了四个四个特殊的名字:

main
all
std
cmd

你可以使用 go list stdgo list cmd 看看效果。

... 代表匹配任何字符串,包括空格和斜杠,但是不会匹配vendor文件夹。

乱。

参考资料

  1. https://golang.org/doc/go1.13#modules
  2. https://blog.golang.org/module-mirror-launch
  3. https://blog.golang.org/migrating-to-go-modules
  4. https://blog.golang.org/using-go-modules
  5. https://blog.golang.org/modules2019
相关文章