文章

Go-知识依赖Module

在 Go 1.11 中,Module 特性被首次引入,Go 的依赖管理经历了 GOPATH, vendor ,进入了 Module 阶段。Go Module 比 GOPATH 和 vendor 强大很多,基本上解决了 GOPATH 和 vendor 存在的问题。GOPATH 最大的困扰是无法让多个项目共享同一个 package 的不同版本,在 vendor 中,通过把每个项目依赖的。_go module规范

Go-知识依赖Module

文章信息

  • 原文链接:https://jiayq.blog.csdn.net/article/details/143203722
  • 发布时间:2024-10-24 11:01:19
  • 阅读量:951
  • 分类:Golang专栏收录该内容, 订阅专栏
  • 标签:#1024程序员节, #go, #golang, #go module, #module, #依赖管理

摘要

文章浏览阅读951次,点赞8次,收藏16次。在 Go 1.11 中,Module 特性被首次引入,Go 的依赖管理经历了 GOPATH, vendor ,进入了 Module 阶段。Go Module 比 GOPATH 和 vendor 强大很多,基本上解决了 GOPATH 和 vendor 存在的问题。GOPATH 最大的困扰是无法让多个项目共享同一个 package 的不同版本,在 vendor 中,通过把每个项目依赖的。_go module规范


Go-知识依赖Module

  • 1. 介绍
  • 2. module 的定义
  • 3. 语义化版本规范
  • 4. 使用例子
    • 4.1 hello world
      • 4.2 初始化 module
      • 4.3 管理依赖
  • 5. module 发展

1. 介绍

在 Go 1.11 中,Module 特性被首次引入,Go 的依赖管理经历了 GOPATH, vendor ,进入了 Module 阶段。
Go Module 比 GOPATH 和 vendor 强大很多,基本上解决了 GOPATH 和 vendor 存在的问题。
GOPATH 最大的困扰是无法让多个项目共享同一个 package 的不同版本,在 vendor 中,通过把每个项目依赖的
package 放到 vendor 中解决这个问题,但是使用 vendor 的问题是无法很好地管理依赖的 package ,比如升级等等。
虽然 Go Module 能够解决 GOPATH 和 vendor 的问题,不过, Go Module 不是 GOPATH 和 vendor 的演进,而是 Go 的升级兼容保证。
Go Module 是一种全新的依赖管理方案,主要优化的问题:1. 准确地记录项目依赖;2. 可重复的构建。
准确地记录项目依赖
是指项目依赖哪些 package ,以及精确的 package 版本,相当于固化一个 package 的快照,不管何时,在任何环境中,
只要能获取到依赖,都能编译项目,不会因为依赖的版本出现不兼容升级,而导致编译失败。
可重复构建
基于准确的记录项目依赖,那么只要大的平台相同,那么任何环境,任何人编译构建的产物是相同的。
不会出现因人而异的 GOPATH 导致,编译产品出现差异。
简单来说,如果某个环境获取不到指定版本的依赖,那么会拒绝编译构建,从而产生不可用的产物。

2. module 的定义

根据 Go 官方文档的定义:

A module is a collection of related Go packages that are versioned together as a single unit. The go.mod file defines the module’s module path, which is also the import path used for the root directory of the module, and its dependency requirements, which are the other modules needed for a successful build.

翻译成中文:

模块是作为单个单元一起版本化的一组相关的 Go 包。go.mod 文件定义了模块的模块路径(也是模块根目录的导入路径)及其依赖要求,即成功构建所需的其他模块。

官方定义的链接

可以在 Go 官方文档中找到关于 Go Module 的详细定义和使用说明:

通常而言,一个仓库包含一个 module (虽然也可以包含多个,但不推荐),所以仓库、module 和 package 的关系如下:

  • 一个仓库包含一个或多个 module
  • 每个 module 包含一个或多个 package
  • 每个 package 包含一个或多个源文件

一个 module 的版本号规则必须遵循语义化规范,版本号必须使用 v(major).(minor).(patch) 格式。

3. 语义化版本规范

语义化版本(Semantic Versioning)已成为事实上的标准,几乎知名的开源项目都遵循该规范。
版本格式 v(major).(minor).(patch) 中的 major 指的是大版本,minor 指小版本,patch 指补丁版本。

  • major: 当发生不兼容的改动时,才可以增加该版本,比如 v2.x.y 与 v1.x.y 是不兼容的
  • minor: 当有新特性时才可以增加该版本,比如 Go 1.11.0 在 Go 1.10.3 的基础上增加了新特性,同时兼容 Go 1.10.3
  • patch: 当有bug修复时,才可以增加该版本,比如 Go 1.11.1 修改了 Go 1.11.0 的bug,但是没有新增特性。

这是 Go 源码的一个版本
https://github.com/golang/go/tags
在这里插入图片描述

语义化版本规范的好处是用户通过版本号就能了解版本信息。

4. 使用例子

4.1 hello world

创建一个项目,里面只包含一个 main.go 文件
在这里插入图片描述

此时项目还没有引用任何第三方包,也未使用Go Module。

4.2 初始化 module

一个项目若要使用 Go Module ,那么其本身需要先成为一个 module ,需要一个 module 名字 (在最新的ide工具中,会自动初始化 module name 等于 project name)。
在 Go Module 机制下,项目的 module 名字及其依赖信息记录在一个名为 go.mod 的文件中,该文件可以手动创建,也可以使用 go mod init 命令自动生成。
go mod init github.com/he/helloworld
在这里插入图片描述

完整的 go mod init 命令格式为 go mod init [module] ,其中 [module]为 module 名字,如果不填,则 go mod init 会尝试从版本控制系统或 import 的注释中猜测一个。
推荐指定明确的 module 名字,因为猜测有时需要一些额外的条件,比如 Go 1.13,只有项目位于 GOPATH 中才可以正确运行, 而 Go 1.11 则没有此要求。
go mod init命令会自动创建一个 go.mod 文件,其中包括 module 名字,以及使用的版本:
在这里插入图片描述

module 的名字用于 import 语句中,如果 module 中包含多个 package ,则 module 的名字就是 package 的前缀。
在 go.mod 文件中记录 Go 的版本号是在 Go 1.12 中引入的小特性,该版本号表示开发此项目的 Go 语言版本,并不是编译该项目所限制的 Go 语言版本。
如果在项目中使用了 Go 1.13 的新特性,而使用 Go 1.11 编译,那么在编译失败时,编译器会给出 Go 版本不匹配的提示。

4.3 管理依赖

引用一个第三方包 github.com/google/uuid 来生成一个 UUID,这样就会产生一个依赖:
在这里插入图片描述

在开始编译前,使用 go get 下载依赖包
在这里插入图片描述

go get 总是获取依赖的最新版本,如果 github.com/google/uuid 发布了新的版本,那么输出的版本信息会相应地变化。
并且该命令会修改 go.mod 文件
在这里插入图片描述

现在 go.mod 中增加了 require github.com/google/uuid v1.6.0 内容,表示当前项目依赖 github.com/google/uuid的 1.6.0版本,这就是 go.mod 记录的依赖信息。
因为这是当前项目第一次引用外部依赖,因此 go get 命令还会生成一个 go.sum 文件,用于记录依赖包的 Hash 值:
在这里插入图片描述

该文件通过记录每个依赖包的 Hash 值来确保将来项目构建时,依赖包不会被篡改。
经过 go get 修改的 go.mod 和创建的 go.sum 都需要提交到代码库,这样别人获取项目代码后,编译时就会使用项目所要求的依赖版本。

5. module 发展

Go Module 在 Go 1.11 中初次引入,历经 Go 1.12,Go 1.13 的发展,最后到 Go 1.14 成熟,部分实现细节上会略有不同。
不过目前项目很少有Go 1.14之前的了,而且Go 保证向后兼容,所以基本上不会担心版本的差异。

本文由作者按照 CC BY 4.0 进行授权