依赖管理 | 青训营笔记

110 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 5 天

Go语言依赖管理

Go的依赖管理主要分为3种:GOPATHGo VendorGo Module,其中Go Module最为常用。

GOPATH

GOPATHGo语言环境变量,是Go项目的工作区:

  1. bin 项目编译的二进制文件
  2. pkg 项目编译的中间产物,加速编译
  3. src 项目源码

GOPATH依赖指的是项目代码直接依赖src下的代码,通过go get下载最新版本的依赖包到src目录下。

弊端

无法实现package的多版本控制。

Go Vendor

Go Vender的出现解决了GOPATH不能多版本控制的麻烦。

Go Vender依赖管理模式在项目目录下增加vendor文件,所有依赖包副本形式放$ProjectRoot/vendor目录下,其依赖寻址方法为vendor=>GOPATH

Go Vender通过每个项目引入一份依赖的副本方式,解决了多个项目需要同一个package依赖的冲突问题。

弊端

Go Vender存在以下问题:

  1. 无法控制依赖的版本
  2. 更新项目又可能出现依赖冲突,导致编译出错。

出现这样问题的原因归根结底还是因为直接依赖的是项目的源码,不能清晰标识版本的概念。

Go Module

Go Module的出现解决了Go Vender出现的问题,可以管理依赖的版本。

Go Module通过go.mod文件管理依赖包的版本,通过go get/go mod指令工具管理依赖包。

Go Module的终极目标为:定义版本规则和管理项目的依赖关系。

依赖管理三要素

依赖管理存在以下三要素:

  1. 配置文件,描述依赖 go.mode
  2. 中心仓库管理依赖库 Proxy
  3. 本地工具 go get/mod

go.mod

go.mod文件配置:

module example/project/app 依赖管理基本单元
go 1.16 原生库
require( 单元依赖
    example/lib1 v1.0.2
    example/lib2 v1.0.0
    example/lib3 v0.1.0-20190725
    example/lib4 v0.0.0-20180036
    example/lib5/v3 v3.0.2
    example/lib6 v3.2.0+incompatible
)
复制代码

依赖标识:[Module Path][Version/Pseudo+version]

module为模块路径,用来标识一个模块,可以根据这个来找到模块,依赖托管的路径。

go为项目依赖原生库的版本号。

require为最关键的一部分,主要是描述单元依赖,主要由两部分组成:Module PathVersion/Pseudo+version

版本定义

go.mod版本主要有两种类型:语义化版本、基于commit伪版本。

语义化版本 组成形式:${MAJOR}.${MINOR}.${PATCH}

示例:V1.3.0、V2.3.0

基于commit伪版本 组成形式:vx.0.0-yyyymmddhhmmss-abcdefgh1234

示例:v0.0.0-20220401081311-c38fb59326b7、v1.0.0-20201130134442-10cb98267c6c

indirect

如果不是直接依赖的模块,用indirect标识出来。

假如依赖关系为:A->B->C,其中A->B为直接依赖,A->C为间接依赖。

incompatible

在依赖后面加上incompatible,代表代码中可能存在不兼容的问题。

Go在处理版本兼容的问题时,会选择最低的兼容版本。

Proxy

依赖是从哪里下载的呢?

比较常见的是GitHubGitHub是一个代码托管平台,但是访问的时候可能存在不稳定性的问题,所以使用代码托管平台下载依赖的话会存在以下几个问题:

  1. 无法保证构建稳定性,可能存在增加、修改、删除软件版本。
  2. 无法保证依赖可用性,软件被删除
  3. 增加第三方压力,代码托管平台负载问题

为了解决这些问题,就出现了Proxy这个概念。

Proxy是一个中间站点,他会缓存软件版本的内容,而且缓存的版本不会改变。

通过Proxy可以保证站点的稳定性、可靠性。

Proxy配置

设置环境变量GOPROXY

GOPROXY="https://proxy1.cn,https://proxy2.cn,direct"

可以配置多个url用逗号分隔,direct代表源站。 在获取依赖时,会从前往后依次查找依赖。

go get

使用示例:go get example.org/pkg + 参数

参数示例:

  1. @update 默认参数
  2. @none 删除依赖
  3. @v1.1.2 指定tag版本,语义版本
  4. @23dfdd5 特定的commit版本
  5. @master 指定分支的最新commit

附加参数:

  1. -d 只下载不安装
  2. -f 只有在你包含了 -u 参数的时候才有效,不验证
  3. -fix 在获取源码之后先运行 fix,然后再去做其他的事情
  4. -t 同时也下载需要为运行测试所需要的包
  5. -u 强制使用网络去更新包和它的依赖包
  6. -v 显示执行的命令日志信息

go mod

使用示例:go mod + 参数

常用参数如下:

  1. download     下载依赖的到本地
  2. edit         编辑go.mod文件
  3. graph       打印模块依赖图
  4. init         初始化当前文件夹, 创建go.mod文件
  5. go mod tidy        拉取缺少的模块,移除不用的模块
  6. go mod vendor      将依赖复制到vendor下
  7. go mod verify      验证依赖是否正确
  8. go mod why         解释为什么需要依赖