Go语言进阶-依赖管理|青训营

45 阅读3分钟

依赖管理

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

出现3种主要目的是围绕2个方面:不同项目依赖的版本不同、控制依赖库的版本。

GO PATH

GOPATHGo支持的一个环境变量,他是Go项目的工作区,有三个关键点:

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

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

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文件配置:

go
复制代码
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

shell
复制代码
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文件 go mod tidy         拉取缺少的模块,移除不用的模块 go mod vendor      将依赖复制到vendor下 go mod verify      验证依赖是否正确 go mod why         解释为什么需要依赖