Dawn's Blogs

分享技术 记录成长

0%

GO语言杂谈 (11) 依赖管理

Go 依赖管理演进

Go 语言中,依赖管理的演进分为三个阶段,依次是:

  • GOPATH
  • Go Vendor
  • Go Module

GOPATH

配置环境变量 $GOPATH,GOPATH 下有以下三个文件夹:

  • bin:项目编译的二进制文件
  • pkg:项目编译的中间产物,用于加速编译
  • src:项目源码

项目的代码直接依赖于 src 下的代码,可以通过 go get 命令将依赖包下载到 src 下。


GOPATH 的缺点在于:无法实现对 package 的多版本控制

若 A 和 B 依赖于某一 package 的不同版本,这样的情况 GOPATH 无法解决。

Go Vendor

项目目录下增加 vendor 文件夹,所有依赖包的副本存放在项目下的 vendor 文件夹中。

若 vendor 中没有依赖包,则会在 GOPATH 下去寻找。


Go Vendor 的缺点在于:无法控制依赖的版本、更新项目可能出现依赖冲突。

若一个项目依赖于 package B 和 packag C,而 package B 依赖于 package D-V1 版本;package C 依赖于 package D-V2 版本。这样的场景下,Go Vendor 无法很好的解决。

1655220603232

Go Module

Go Module 通过 go.mod 文件管理依赖包版本。

通过 go get / go mod 工具,管理依赖包。

Go Module 详解

依赖管理三要素

Go Module 中,依赖管理需要三要素:

  • go.mod:配置文件,描述依赖。
  • Proxy:中心仓库管理依赖库。
  • go get/mod:本地工具。

go.mod

go.mod 文件主要由三部分构成:

  • 依赖管理基本单元:标识了这个模块可以在哪里找到(被其他人引用)。
  • 原生库:Go 的版本号。
  • 单元依赖:描述依赖关系,主要两部分组成。
    • 包名(Module Path)
    • 版本号

1655220918315

其中,可以看到单元依赖的一些配置:

  • version:
    • 语义化版本${MAJOR}.${MINOR}.${PATCH}MAJOR 是一个大版本,不同 MAJOR 可以不兼容MINOR 做出了一些新增函数,同一个 MAJOR 下需要相互兼容PATCH 做了一些 bug 修复。
    • 基于 commit 伪版本vx.0.0-yyyymmddhhmmss-abcdefgh1234
  • indirect:对于没有直接依赖的 package,就用 indirect 标识出来。
  • incompatible:如果 MAJOR 版本大于 1 时,其版本号还需要体现在 Module 名字中(如 xxx/xx/v2)。但是如果 Module 名字未遵循这条规则,则会打上 incompatible 标记。

Go 在选择版本时,会选择最低的兼容版本

如下图中,最终编译时所使用的 C 项目版本为 1.4 版本。

1655221776213

Proxy

Go Proxy 是一个服务站点,他会缓存源站中的软件内容,缓存的软件版本不会改变,源站软件删除后依然可用。

1655221901310

GOPROXY="https://proxy1.cn,https://proxy2.cn,direct",含义是依次从 proxy1、proxy2、源站中获取 package。

go get/mod

  • go getgo get example.org/pkg,参数如下:

    • @update:默认,获取最新版本。
    • @none:删除依赖。
    • @v1.1.1:语义化版本。
    • @45dfsf:特定的 commit。
    • @master:分支的最新 commit。
  • go mod:参数如下:

    • init:初始化,创建 go.mod 文件。
    • download:下载模块到本地。
    • tidy:增加需要的依赖,删除不需要的依赖。