青训营X豆包MarsCode 技术训练营之GO语言进阶(二)| 豆包MarsCode AI 刷题

70 阅读5分钟

1.1依赖管理
1.1.1 GOPATH 目前为止,Go的依赖管理主要经历了三个阶段:
GOPATH->Go Vender->Go Module

整个路线主要围绕着实现下面两个目标来迭代发展的:
不同环境(项目)依赖版本不同
控制依赖库的版本

CSDN_1732512874965.png 所有工程代码要求放在GOPATH/src目录下
工程本身也将作为一个依赖包,可以被其它 GOPATH/src 目录下的工程引用在 $GOPATH/src 下进行 .go 文件或源代码的存储,我们可以称其为 GOPATH 的模式

弊端

CSDN_1732512954656.png 没有版本控制的概念
所有的项目需要存放在$GOPATH/src目录下,否则就不能编译。

1.1.2 Go Vender 解决 GOPATH模式 所有项目都在$GOPATH/src目录的问题,可以随处可以创建项目,不用扎堆src 目录下。
通过每个项目引入一份依赖的副本,解决了多个项目需要同一个package依赖开的冲突问题。

CSDN_1732513088424.png 项目目录西卡增加了vender文件,所有的依赖包副本形式存放在ProjectRoot/vender下。
依赖的寻址方式:vender->GOPATH

不足

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

1.1.3 GoModule
通过go.mod文件管理依赖包版本
通过go get/go mod指令工具管理依赖包
实现定义版本规则和管理项目依赖关系,类比Java中的Maven。

核心三要素
配置文件,描述依赖-go.mod
中央仓库管理依赖库-Proxy
本地工具-go get/mod
go.mod

启用了 Go modules 的项目,初始化项目时,会生成一个 go.mod 文件。描述了当前项目(也就是当前模块)的元信息。CSDN_1732513240500.png 首先模块路径用来标识一个模块,从模块路径可以看出来从哪里找到该模块,如果是clone自github,则前缀就是Github仓库,依赖包的源代码由github托管。
如果项目的子包想被单独的引用,就需要通过单独的init go。mod文件进行管理。

版本管理 gopath和govender都是源码副本方式依赖,没有版本规则的概念,而gomod为了方便管理定义了版本规则,分为语义化版本和 基于commit的伪版本。
在语义化版本规则中,不同的MAJOR版本表示不兼容的API,所以即使是同一个库,MAJOR版本不同也不会被认为为是不同的模块;
MINOR版本通常是新增函数或者功能,向后兼容;而PATCH版本一般是修复BUG;
基于commit的版本中,基础版本前缀和语义化版本一样,时间戳(yyyymmddhhmmss)也就是该提交Commmit的时间,最后的校验码部分包含了12位的哈希前缀,每次提交commit后go都会默认生成一个伪版本号。gopath和govender都是源码副本方式依赖,没有版本规则的概念,而gomod为了方便管理定义了版本规则,分为语义化版本和 基于commit的伪版本。
在语义化版本规则中,不同的MAJOR版本表示不兼容的API,所以即使是同一个库,MAJOR版本不同也不会被认为为是不同的模块;
MINOR版本通常是新增函数或者功能,向后兼容;而PATCH版本一般是修复BUG;
基于commit的版本中,基础版本前缀和语义化版本一样,时间戳(yyyymmddhhmmss)也就是该提交Commmit的时间,最后的校验码部分包含了12位的哈希前缀,每次提交commit后go都会默认生成一个伪版本号。

indirect

CSDN_1732513370485.png indirect是依赖单元中的特殊标识符之一,以后缀的形式存在,表示go.mod对应的当前模块,没有直接导入该依赖的包,也就是非直接依赖,标识间接依赖,如:

CSDN_1732513374185.png 在执行命令go mod tidy时,Go module 会自动整理go.mod 文件,如果有必要会在部分依赖包的后面增加// indirect注释。一般而言,被添加注释的包肯定是间接依赖的包,而没有添加// indirect注释的包则是直接依赖的包,即明确的出现在某个import语句中。

依赖图
github是比较常见的代码托管平台,而Go Modules系统中定义的依赖,最终可以对应到多版本代码管理系统中某一个项目的特定提交版本,这样的话,对于go mod中定义的依赖,则直接可以从对应仓库中下载指定的软件依赖,从而完成依赖分发。
但是直接使用版本管理仓库下载依赖,会存在一些问题,比如无法保证构建确定性,软件作者可以直接在代码平台对软件的版本进行增删改查,导致下次构建使用的是另外一个版本依赖,或者找不到依赖版本,无法保证依赖的可用性,依赖软件作者可以直接在平台删除软件,导致依赖不可用,大幅度增加第三方代码托管平台的压力。 基于此,可以使用下面的Proxy的方式解决这些问题。

proxy

CSDN_1732513542631.png go proxy是一个服务站点,他会缓存源站中的软件名称,缓存的软件版本不会改变,并且在源软件删除之后依然可以用,从而实现了供immutability和available的依赖分发;使用proxy之后,构建时会直接从proxy站点拉取依赖。

变量GOPROXY

GOPROXY="proxy1.cn,https://proxy2.cn ,direct"服务站点URL列表,"direct”表示源站。
go module通过goproxy环境变量控制如何使用go proxy;goproxy是一个goproxy站点的URL列表,可以使用direct表示源站。对于示例配置,整体的依赖寻找路径,会优先从proxy下载依赖,如果proxy1不存在,会从proxy2继续寻找,如果proxy2z中不存在则会返回到源站直接下载依赖,缓存到proxy站点中。

go mod

CSDN_1732513600414.png