go mod 使用教程

go mod使用简介

go mod是什么

  • Golang从诞生之初就一直有个被诟病的问题:缺少一个行之有效的“官方”包依赖管理工具。其原因是在Google内部,所有人都是在一个代码库上进行开发的,因此并不是非常需要。但Golang变成一个社区化的工程语言之后,这个问题被放大了。

  • GOPATH不符合一般开发者习惯,大部分人更习惯maven、node modules之类的方式

  • GOPATH无法有效的管理版本依赖,没有一个地方能够表明依赖包的具体版本号,无法形成有效的版本配套关系

  • 在Golang 1.5发布了vendor特性之后,社区在vendor基础上开发了很多包管理工具,例如glide, dep(这个最悲催,已经半官方了,结果横刀杀出来一个go mod),等等,具体参见拙文go依赖包管理工具对比 。但说实话,都不是非常满意。

  • 你可能会说dep,glide我用的都挺爽的,有什么不满意的?

  • 其实我不喜欢的是vendor这个特性。开发过前端的同学对node modules一定印象深刻,得益于前端混乱的包管理,一个普通的web前端,其node modules往往非常巨大,而且它是每工程的,也就是说如果有2个前端工程,就会有两份巨大的node moudles,里面有成千上万个文件,常常造成IDE挂死,也非常浪费硬盘。

  • 那么,vendor是不是到后期也会变成这样呢?同样的库,同样的版本,就因为在不同的工程里用了,就要在vendor里单独搞一份,不浪费吗?所以这些基于vendor的包管理工具,都会有这个问题。

  • 相比之下maven这种本地缓存库的管理方式就好很多。

  • Golang 1.11 版本引入的 go mod ,其思想类似maven:摒弃vendor和GOPATH,拥抱本地库。

  • 先来看看怎么用。

go mod 具体介绍

前提工作

  • 把 golang 升级到 1.11(现在1.12 已经发布了,建议使用1.12)

  • 设置 GO111MODULE

GO111MODULE

  • GO111MODULE 有三个值:off, on和auto(默认值)。
    • GO111MODULE=off,go命令行将不会支持module功能,寻找依赖包的方式将会沿用旧版本那种通过vendor目录或者GOPATH模式来查找。
    • GO111MODULE=on,go命令行会使用modules,而一点也不会去GOPATH目录下查找。
    • GO111MODULE=auto,默认值,go命令行将会根据当前目录来决定是否启用module功能。这种情况下可以分为两种情形:
      • 当前目录在GOPATH/src之外且该目录包含go.mod文件
      • 当前文件在包含go.mod文件的目录下面。
1
当modules 功能启用时,依赖包的存放位置变更为$GOPATH/pkg,允许同一个package多个版本并存,且多个项目可以共享缓存的 module。

go mod 命令

  • golang 提供了 go mod命令来管理包。

go mod 命令

  • go mod 有以下命令:
命令 说明
download download modules to local cache(下载依赖包)
edit edit go.mod from tools or scripts(编辑go.mod)
graph print module requirement graph (打印模块依赖图)
init initialize new module in current directory(在当前目录初始化mod)
tidy add missing and remove unused modules(拉取缺少的模块,移除不用的模块)
vendor make vendored copy of dependencies(将依赖复制到vendor下)
verify verify dependencies have expected content (验证依赖是否正确)
why explain why packages or modules are needed(解释为什么需要依赖)

go mod 使用

新项目

  • 1.在GOPATH 目录之外新建一个目录,并使用go mod init 初始化生成go.mod 文件

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    ➜  ~> mkdir hello
    ➜ ~> cd hello
    ➜ ~/hello> go mod init hello
    go: creating new go.mod: module hello
    ➜ ~/hello> ls
    go.mod
    ➜ ~/hello> cat go.mod
    module hello

    go 1.13
  • go命令(‘go build’, ‘go test’, 甚至 ‘go list’)执行时,会自己去修改go.mod文件。

go mod 的拉取指定版本

  • 在go.mod中指定版本

  • 在使用go get 如果我们想指定一些版本信息, 可以参照下面的操作:

    1
    2
    3
    4
    5
    // 根据tag
    go get -u github.com/gin-gonic/gin@v1.3.0

    // 根据commit id
    go get github.com/xx/xx@0f1dbe038589903023daa297102f8688641dbe73

Tips

  • 此外,一些墙外的包(golang.org/x/…)如果下载有问题,可以说设置代理
    1
    export GOPROXY=https://goproxy.io