上一篇文章中,我们介绍了 GoLang 中包的使用与包管理机制。 GoLang 包的使用与管理
从 GoLang 1.11 版本开始,官方推出了一个崭新的包管理工具 — go module,随着 GoLang 1.13 版本的发布,go module 默认开启,官方开始强推 go module,使用 go module 作为包管理工具已经成为了官方倡导的趋势。 本文,我们就来详细介绍一下 go module 的使用。
go module 的设计思想是改变原有的基于仓库管理 golang 包的模式,而是通过更加灵活的“模块”来进行包管理,每个包含 go.mod 文件的目录都是一个模块,从而实现:
正如上面所说,go.mod 文件是 go module 模式的关键,他定义了模块的依赖关系。
go.mod 拥有四个指令 module
, require
, replace
, exclude
:
下面是一个 go.mod 的例子:
module github.com/hilaily/test
require (
github.com/gopkg/go-client v0.0.0-20170930090034-2628b1bfb590 // indirect
github.com/gin/ginex v1.3.0
github.com/gopkg/consul v1.0.4
)
replace (
github.com/test/a v0.0.0-20190603160528-e2879d2603b8 => github.com/test/a v0.0.0-20190704135338-bf0b0a45db46
github.com/test/a v0.0.0-20190611023130-5ee11b162b30 => github.com/test/a v0.0.0-20190704135338-bf0b0a45db46
)
go module 的版本通过仓库的 tag 来确定。 在 $GOPATH/pkg/mod 目录下,通过分层的目录结构实现包的管理,在最深一层,通过包最后一段名称@version 来实现包版本的管理。 事实上,在实际的开发中,master 上的重要版本都打上 tag 是一个好习惯。 如果没有 tag,go 会使用 v0.0.0-<time>-<commit id> 的形式记录版本。
GoLang 模块版本号遵循 Semantic Versioning 2.0.0 协议:
需要注意的是,v0.x.x、v1.x.x 与 v2 以上版本具有不同的特性:
关于第三点,下面是不同场景下包引入路径的变化:
如果将一个包从 v1.x.x 提升到 v2 以上版本,所有引入路径都需要修改,这是一个工作量很大且十分容易出错的工作,可以使用开源工具来实现包版本的变更:
https://github.com/marwan-at-work/mod
有些包在 go.mod 中,版本号显示的是:
v3.2.1+incompatible
+incompatible 表示该依赖打了 tag,但这个仓库不是一个 go module。
通过设置环境变量 GO111MODULE=on 可以打开 go module,默认是 auto,指的是如果项目不在 GOPATH 下,则开启 go module。从 GoLang 1.13 开始,默认的 auto 意味着,只要当前目录具有 go.mod,那么无论项目在哪里,都开启 go module。
开启 go module 以后,通过 $GOPROXY 环境变量可以设置代理服务器,例如:
export GOPROXY="https://goproxy.cn,direct"
GOPRIVATE 与 GONOPROXY 两个环境变量是一样的, 他们定义了哪些仓库是不需要经过代理的,例如:
export GOPRIVATE="*.corp.example.com,rsc.io/private"
对于新项目或已有的非 go module 管理的项目,可以执行下面的命令来进行初始化:
go mod init <packagename>
packagename 是模块的引入路径,例如 github.com/pkg/test 等。 初始化完成后,在当前目录会自动生成 go.mod 文件,里面只有一行文本:
module github.com/pkg/test
你可以参考上文,在 go.mod 中手动添加依赖的模块。 通过下面的命令,可以将 go.mod 中声明的包下载到本地:
go mod download
也可以通过执行 go get 命令获取依赖:
go get github.com/pkg/xxx@v1.0.1
@v1.0.1 指定了版本,如果不指定则会自动寻找 v1 版本以下的最新版本。 同时,你也可以指定 @latest 来要求 golang 自动更新到最新版本。 你也可以换成指定的 commit_id:
例如:
go get -u github.com/pkg/xxx@v1.2.1
完成代码的编写后,执行 go build 或 go test 命令,相应工具会自动拉取依赖。
在编写代码的过程中,往往会在 go.mod 文件中添加过多的依赖,golang 也提供了相应工具来整理依赖,增加丢失的依赖,删除无用依赖:
go mod tidy
通过命令 go get 增加 -u 参数,可以将指定包升级到指定版本:
他会把 go.mod 的 latest 版本换成实际的最新的版本,并且会生成一个 go.sum 记录每个依赖库的版本和哈希值。
通过 go list all 命令可以列出项目依赖的所有包。
go module 支持使用 go mod why 的模式查询项目为什么需要某个依赖,例如:
go mod why -m github.com/pkg/test
会输出从当前项目到 github.com/pkg/test 这个模块的最短依赖链。
go mod graph 输出结果有两列,前者是一个库,后者是它的依赖。 通过这个输出,我们可以绘制整个项目依赖的有向无环图。
https://github.com/golang/go/wiki/Modules#is-it-possible-to-add-a-module-to-a-multi-module-repository。 https://semver.org/ https://colobu.com/2018/08/27/learn-go-module/ https://roberto.selbach.ca/intro-to-go-modules/ https://colobu.com/2019/09/23/review-go-module-again/
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有