go modules
是 golang 1.11 新加的特性。现在1.12 已经发布了,是时候用起来了。Modules官方定义为:
模块是相关Go包的集合。modules是源代码交换和版本控制的单元。 go命令直接支持使用modules,包括记录和解析对其他模块的依赖性。modules替换旧的基于GOPATH的方法来指定在给定构建中使用哪些源文件。
如何使用 Modules ?
- 把 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文件的目录下面。
当modules 功能启用时,依赖包的存放位置变更为
$GOPATH/pkg
,允许同一个package多个版本并存,且多个项目可以共享缓存的 module。
go mod
golang 提供了 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(解释为什么需要依赖) |
如何在项目中使用
示例一:创建一个新项目
- 在
GOPATH 目录之外
新建一个目录,并使用go mod init
初始化生成go.mod
文件
go.mod文件一旦创建后,它的内容将会被go toolchain全面掌控。go toolchain会在各类命令执行时,比如go get、go build、go mod等修改和维护go.mod文件。
go.mod 提供了module
, require
、replace
和exclude
四个命令
module
语句指定包的名字(路径)require
语句指定的依赖项模块replace
语句可以替换依赖项模块exclude
语句可以忽略依赖项模块
- 添加依赖
新建一个 server.go 文件,写入以下代码:
执行 go run server.go
运行代码会发现 go mod 会自动查找依赖自动下载:
|
|
现在查看go.mod 内容:
|
|
go module 安装 package 的原則是先拉最新的 release tag,若无tag则拉最新的commit,详见 Modules官方介绍。 go 会自动生成一个 go.sum 文件来记录 dependency tree:
|
|
- 再次执行脚本
go run server.go
发现跳过了检查并安装依赖的步骤。 - 可以使用命令
go list -m -u all
来检查可以升级的package,使用go get -u need-upgrade-package
升级后会将新的依赖版本更新到go.mod * 也可以使用go get -u
升级所有依赖
go get 升级
- 运行 go get -u 将会升级到最新的次要版本或者修订版本(x.y.z, z是修订版本号, y是次要版本号)
- 运行 go get -u=patch 将会升级到最新的修订版本
- 运行 go get package@version 将会升级到指定的版本号version
- 运行go get如果有版本的更改,那么go.mod文件也会更改
示例二:改造现有项目(helloword)
项目目录为:
server.go 源码为:
api/apis.go 源码为:
- 使用
go mod init ***
初始化go.mod
- 运行
go run server.go
|
|
首先还是会查找并下载安装依赖,然后运行脚本 server.go
,这里会抛出一个错误:
|
|
但是go.mod
已经更新:
|
|
那为什么会抛出这个错误呢?
这是因为 server.go 中使用 internal package 的方法跟以前已经不同了,由于 go.mod会扫描同工作目录下所有 package 并且变更引入方法
,必须将 helloworld当成路径的前缀,也就是需要写成 import helloworld/api,以往 GOPATH/dep 模式允许的 import ./api 已经失效,详情可以查看这个 issue。
- 更新旧的package import 方式
所以server.go 需要改写成:
一个小坑
:开始在golang1.11 下使用go mod 遇到过go build github.com/valyala/fasttemplate: module requires go 1.12
这种错误,遇到类似这种需要升级到1.12 的问题,直接升级golang1.12 就好了。幸亏是在1.12 发布后才尝试的go mod
🤷♂️
- 到这里就和新创建一个项目没什么区别了
使用replace替换无法直接获取的package
由于某些已知的原因,并不是所有的package都能成功下载,比如:golang.org
下的包。
modules 可以通过在 go.mod 文件中使用 replace 指令替换成github上对应的库,比如:
或者
|
|
参考链接
- Modules官方介绍
- Golang 1.11 新功能介紹 – Modules
- What are Go modules and how do I use them?
- go mod doesn’t work for github.com/gomarkdown/markdown/html
- 再探go modules:使用与细节
- 初窥Go module
References
[1] Modules官方介绍: https://github.com/golang/go/wiki/Modules [2] issue: https://github.com/golang/go/issues/26645 [3] 这种错误: https://github.com/golang/go/issues/27565 [4] Modules官方介绍: https://github.com/golang/go/wiki/Modules [5] Golang 1.11 新功能介紹 – Modules: https://www.lightblue.asia/golang-1-11-new-festures-modules/?doing_wp_cron=1552464864.6369309425354003906250 [6] What are Go modules and how do I use them?: https://talks.godoc.org/github.com/myitcv/talks/2018-08-15-glug-modules/main.slide#1 [7] go mod doesn’t work for github.com/gomarkdown/markdown/html : https://github.com/golang/go/issues/27565 [8] 再探go modules:使用与细节: https://www.cnblogs.com/apocelipes/p/10295096.html [9] 初窥Go module: https://tonybai.com/2018/07/15/hello-go-module/
最后,感谢女朋友支持和包容,比❤️
也可以在公号输入以下关键字获取历史文章:公号&小程序
| 设计模式
| 并发&协程