前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >GoLang 新版包管理 -- go module 的使用

GoLang 新版包管理 -- go module 的使用

作者头像
用户3147702
发布2022-06-27 14:14:19
1.9K0
发布2022-06-27 14:14:19
举报
文章被收录于专栏:小脑斧科技博客

1. 引言

上一篇文章中,我们介绍了 GoLang 中包的使用与包管理机制。 GoLang 包的使用与管理

从 GoLang 1.11 版本开始,官方推出了一个崭新的包管理工具 — go module,随着 GoLang 1.13 版本的发布,go module 默认开启,官方开始强推 go module,使用 go module 作为包管理工具已经成为了官方倡导的趋势。 本文,我们就来详细介绍一下 go module 的使用。

2. go module 的设计思想

2.1. 模块

go module 的设计思想是改变原有的基于仓库管理 golang 包的模式,而是通过更加灵活的“模块”来进行包管理,每个包含 go.mod 文件的目录都是一个模块,从而实现:

  1. 一个仓库包含一个或者多个模块
  2. 一个模块包含一个或多个包
  3. 一个包包含该目录下的所有 go 源码文件

2.2. go.mod

正如上面所说,go.mod 文件是 go module 模式的关键,他定义了模块的依赖关系。 go.mod 拥有四个指令 module, require, replace, exclude

  • module — 用来定义当前模块名称
  • require — 描述依赖信息
  • replace — 用于用指定依赖(后者)去代替前者,比如用 github 的仓库项目替代 goalng.org
  • exclude — 用来忽略某些特定版本

下面是一个 go.mod 的例子:

代码语言:javascript
复制
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
)

3. go module 与版本

go module 的版本通过仓库的 tag 来确定。 在 $GOPATH/pkg/mod 目录下,通过分层的目录结构实现包的管理,在最深一层,通过包最后一段名称@version 来实现包版本的管理。 事实上,在实际的开发中,master 上的重要版本都打上 tag 是一个好习惯。 如果没有 tag,go 会使用 v0.0.0-<time>-<commit id> 的形式记录版本。

3.1. Semantic Versioning 2.0.0 协议

GoLang 模块版本号遵循 Semantic Versioning 2.0.0 协议:

  • 所有版本号都以 v 开头 — v<major>.<minor>.<patch>
  • major — 主版本号,当与之前版本不兼容时提升
  • minor — 次版本号,发布向下兼容的新 feature 时提升
  • patch — 修订版本号,发布 bug fix 时提升

3.2. 测试版与正式版之间的兼容性

需要注意的是,v0.x.x、v1.x.x 与 v2 以上版本具有不同的特性:

  1. v0.x.x — 测试版本,不要求小版本间需要保证兼容性
  2. v1.x.x — 首个正式版本,从 v0 升级到 v1 版本引用路径无需变更
  3. 当主版本号大于等于 v2 时,这个模块的引用路径末尾必须加上 vN

3.3. v2 以上版本引入路径的变化

关于第三点,下面是不同场景下包引入路径的变化:

  • 在 go.mod 文件中: module github.com/my/mod/v2
  • 在 require 的时候:require github.com/my/mod/v2 v2.0.0
  • 在 import 的时候: import "github.com/my/mod/v2/mypkg"

如果将一个包从 v1.x.x 提升到 v2 以上版本,所有引入路径都需要修改,这是一个工作量很大且十分容易出错的工作,可以使用开源工具来实现包版本的变更:

https://github.com/marwan-at-work/mod

3.4. +incompatible

有些包在 go.mod 中,版本号显示的是:

v3.2.1+incompatible

+incompatible 表示该依赖打了 tag,但这个仓库不是一个 go module。

4. go module 的开启与配置

4.1. 开启 go module

通过设置环境变量 GO111MODULE=on 可以打开 go module,默认是 auto,指的是如果项目不在 GOPATH 下,则开启 go module。从 GoLang 1.13 开始,默认的 auto 意味着,只要当前目录具有 go.mod,那么无论项目在哪里,都开启 go module。

4.2. 相关环境变量

4.2.1. 代理

开启 go module 以后,通过 $GOPROXY 环境变量可以设置代理服务器,例如:

export GOPROXY="https://goproxy.cn,direct&quot;

4.2.2. 不使用代理的仓库

GOPRIVATE 与 GONOPROXY 两个环境变量是一样的, 他们定义了哪些仓库是不需要经过代理的,例如:

export GOPRIVATE="*.corp.example.com,rsc.io/private"

5. go module 的使用

5.1. 初始化

对于新项目或已有的非 go module 管理的项目,可以执行下面的命令来进行初始化:

go mod init <packagename>

packagename 是模块的引入路径,例如 github.com/pkg/test 等。 初始化完成后,在当前目录会自动生成 go.mod 文件,里面只有一行文本:

代码语言:javascript
复制
module github.com/pkg/test

5.2. 添加依赖

5.2.1. 手动添加

你可以参考上文,在 go.mod 中手动添加依赖的模块。 通过下面的命令,可以将 go.mod 中声明的包下载到本地:

go mod download

5.2.2. go get 获取

也可以通过执行 go get 命令获取依赖:

go get github.com/pkg/xxx@v1.0.1

@v1.0.1 指定了版本,如果不指定则会自动寻找 v1 版本以下的最新版本。 同时,你也可以指定 @latest 来要求 golang 自动更新到最新版本。 你也可以换成指定的 commit_id:

  • gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7
  • gopkg.in/vmihailenco/msgpack.v2 v2.9.1
  • gopkg.in/yaml.v2 <=v2.2.1
  • github.com/tatsushid/go-fastping v0.0.0-20160109021039-d7bb493dee3e
  • go get github.com/pkg/xxx@latest

例如:

go get -u github.com/pkg/xxx@v1.2.1

5.2.3. 自动拉取依赖

完成代码的编写后,执行 go build 或 go test 命令,相应工具会自动拉取依赖。

5.3. 依赖整理

在编写代码的过程中,往往会在 go.mod 文件中添加过多的依赖,golang 也提供了相应工具来整理依赖,增加丢失的依赖,删除无用依赖:

go mod tidy

5.4. 升级依赖

通过命令 go get 增加 -u 参数,可以将指定包升级到指定版本:

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

他会把 go.mod 的 latest 版本换成实际的最新的版本,并且会生成一个 go.sum 记录每个依赖库的版本和哈希值。

5.5. 依赖查询

5.5.1. go list all

通过 go list all 命令可以列出项目依赖的所有包。

5.5.2. go mod why

go module 支持使用 go mod why 的模式查询项目为什么需要某个依赖,例如:

go mod why -m github.com/pkg/test

会输出从当前项目到 github.com/pkg/test 这个模块的最短依赖链。

5.5.3. go mod graph

go mod graph 输出结果有两列,前者是一个库,后者是它的依赖。 通过这个输出,我们可以绘制整个项目依赖的有向无环图。

6. 参考资料

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/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-11-25,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 小脑斧科技博客 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 引言
  • 2. go module 的设计思想
    • 2.1. 模块
      • 2.2. go.mod
      • 3. go module 与版本
        • 3.1. Semantic Versioning 2.0.0 协议
          • 3.2. 测试版与正式版之间的兼容性
            • 3.3. v2 以上版本引入路径的变化
              • 3.4. +incompatible
              • 4. go module 的开启与配置
                • 4.1. 开启 go module
                  • 4.2. 相关环境变量
                    • 4.2.1. 代理
                    • 4.2.2. 不使用代理的仓库
                • 5. go module 的使用
                  • 5.1. 初始化
                    • 5.2. 添加依赖
                      • 5.2.1. 手动添加
                      • 5.2.2. go get 获取
                      • 5.2.3. 自动拉取依赖
                    • 5.3. 依赖整理
                      • 5.4. 升级依赖
                        • 5.5. 依赖查询
                          • 5.5.1. go list all
                          • 5.5.2. go mod why
                          • 5.5.3. go mod graph
                      • 6. 参考资料
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档