跳出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 一些帮助。

  1. GO111MODULE
    要使用 go module, 首先要设置 GO111MODULE=on, 这没什么可说的,如果没设置,执行命令的时候会有提示,这个大家应该都了解了。

  2. 既有项目
    假设你已经有了一个 go 项目, 比如在 $GOPATH/github.com/smallnest/rpcx下, 你可以使用 go mod init github.com/smallnest/rpcx在这个文件夹下创建一个空的 go.mod (只有第一行 module github.com/smallnest/rpcx)。
    然后你可以通过 go get -m ./...让它查找依赖,并记录在 go.mod文件中 (你还可以指定 -tags, 这样可以把 tags 的依赖都查找到)。
    通过 go mod tidy也可以用来为 go.mod增加丢失的依赖,删除不需要的依赖,但是我不确定它怎么处理 tags。
    执行上面的命令会把 go.mod的 latest版本换成实际的最新的版本,并且会生成一个 go.sum 记录每个依赖库的版本和哈希值。

  3. 新的项目
    你可以在 GOPATH之外创建新的项目。
    go mod init packagename可以创建一个空的 go.mod, 然后你可以在其中增加 require github.com/smallnest/rpcx latest依赖,或者像上面一样让 go 自动发现和维护。
    go mod download可以下载所需要的依赖,但是依赖并不是下载到 $GOPATH中,而是 $GOPATH/pkg/mod中,多个项目可以共享缓存的 module。

  4. go mod 命令


  1. download    download modules to local cache (下载依赖的module到本地cache))

  2. edit        edit go.mod from tools or scripts (编辑go.mod文件)

  3. graph       print module requirement graph (打印模块依赖图))

  4. init        initialize new module in current directory (再当前文件夹下初始化一个新的module, 创建go.mod文件))

  5. tidy        add missing and remove unused modules (增加丢失的module,去掉未用的module)

  6. vendor      make vendored copy of dependencies (将依赖复制到vendor下)

  7. verify      verify dependencies have expected content (校验依赖)

  8. why         explain why packages or modules are needed (解释为什么需要依赖)

有些命令还有 bug, 比如 go mod download -dir:


  1. go mod download -dir /tmp

  2. flag provided but not defined: -dir

  3. usage: go mod download [-dir] [-json] [modules]

  4. Run 'go help mod download' for details.

帮助里明明说可以设置 dir, 但是实际却不支持 dir 参数。
看这些命令的帮助已经比较容易了解命令的功能。

5.
在国内访问 golang.org/x的各个包都需要,你可以在 go.mod中使用 replace 替换成 github 上对应的库。


  1. replace (

  2.    golang.org/x/crypto v0.0.0-20180820150726-614d502a4dac => github.com/golang/crypto v0.0.0-20180820150726-614d502a4dac

  3.    golang.org/x/net v0.0.0-20180821023952-922f4815f713 => github.com/golang/net v0.0.0-20180826012351-8a410e7b638d

  4.    golang.org/x/text v0.3.0 => github.com/golang/text v0.3.0

  5. )

依赖库中的 replace 对你的主 go.mod 不起作用,比如 github.com/smallnest/rpcx的 go.mod 已经增加了 replace, 但是你的 go.mod 虽然 require 了 rpcx 的库,但是没有设置 replace 的话, go get 还是会访问 golang.org/x

所以如果想编译那个项目,就在哪个项目中增加 replace。

6. 版本格式
下面的版本都是合法的:


  1. gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7

  2. gopkg.in/vmihailenco/msgpack.v2 v2.9.1

  3. gopkg.in/yaml.v2 <=v2.2.1

  4. github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3e

  5. latest

7. go get 升级
运行 go get -u 将会升级到最新的次要版本或者修订版本 (x.y.z, z 是修订版本号, y 是次要版本号)
运行 go get -u=patch 将会升级到最新的修订版本
运行 go get package@version 将会升级到指定的版本号 version


8. go mod vendor
go mod vendor 会将 modules 下载到 vendor 中


你可能感兴趣的:(跳出Go module的泥潭)