Go 语言进阶——依赖管理| 青训营笔记

·  阅读 1604

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

前言

本文主要介绍Go语言依赖管理的演进路线以及Go Module实践。

这里的依赖指的是在开发过程中用到的各种开发包,使用别人开发好的组件、工具来提升自己的开发效率。

背景

在使用Go编写一些简单的单体函数时,不需要引入别的依赖,仅使用SDK内置功能即可完成日常开发。

但在实际项目的开发中,功能相对比较复杂,我们不可能只使用SDK标准库从0到1来完成开发,这样会累死人的,老板也不愿意。我们可以利用别人开发好的工具、框架等引入我们的项目中,避免重复造轮子。

随着依赖的增多,依赖管理越发重要。

依赖管理

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

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

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

总结

本文主要介绍Go语言依赖管理的演进路线以及Go Module实践。

引用

Go 语言进阶与依赖管理

分类:
阅读
标签:
收藏成功!
已添加到「」, 点击更改