Go的依赖管理

Go依赖管理的历史进程

GOPATH -> Go Vendor -> Go Module

GOPATH

简介

GOPATH是Go语言支持的一个环境变量$GOPATH
文件结构

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

项目代码直接依赖src下的代码
go get 下载最新版本的包到src目录下

弊端

无法实现package的多版本控制

Go Vendor

  • 在项目目录下增加了vendor文件,所有依赖包的副本形式放在$ProjectRoot/vendor
  • 依赖寻址方式:vendor =>GOPATH

结构

  • README.md
  • dao
  • handler
  • main.go
  • service
  • vendor

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

弊端

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

Go Module

  • 通过go.mod文件管理依赖包版本
  • 通过go get/go mod指令工具管理依赖包

终极目标:定义版本规则和管理项目依赖关系

三要素

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

作用

  • 定义当前模块的名称。
  • 管理模块的依赖关系,包括依赖模块的名称和版本。
  • 指定当前模块所使用的 Go 版本。
  • 提供额外的配置选项,比如替换模块、限制依赖版本等。

经典结构

module example.com/myapp //依赖管理的基本单元

go 1.21	原生库

require (			// 单元依赖
    github.com/gin-gonic/gin v1.9.0
    github.com/stretchr/testify v1.8.4
)

replace github.com/old/module => github.com/new/module v1.2.0

各部分含义:

  • model:
    定义当前模块路径,通常是项目的根路径(可以是域名,也可以是本地路径)
  • go
    指定当前模块所支持的go版本
  • require:
    列出模块的依赖项及其版本
  • replace
    用于替换模块依赖的源,可以指定另一个模块和路径
  • exclude:
    排除某些版本,防止他们被使用
    例如:exclude github.com/buggy/module v1.0.0

依赖项的版本

Go模块管理中,依赖项的版本可以使用语义化版本或基于commit的伪版本

语义化版本

语义化版本简称SemVer是一种版本编号规则格式为

vMAJOR.MINOR.PATCH
  • MAJOR(主版本号)
    • 如果存在不向后兼容的更改,主版本号递增
  • MINOR(次版本号)
    • 如果增加了新功能但没有破坏兼容性,次版本号递增
  • PATCH(修订号)
    • 修复了漏洞或错误但没有改变接口时,修订号递增

优点:

  • 清晰易读
  • 自动兼容性管理,Go模块工具可以根据需求选择合适的版本

示例:
在go.mod文件中配置

require github.com/gin-gonic/gin v1.7.0
基于commit的伪版本(Pseudo-Version)

伪版本是基于Git提交信息生成的一个特殊的版本号,用在以下的场景替代正式的语义化版本:
1.模块尚未发布正式版本
2.需要引用特定的Git提交
3.需要在开发的过程中测试未发布的代码

格式:

vX.Y.Z-yyyymmddhhmmss-commit
  • vX.Y.Z
    基于最后一个语义化版本号(如果没有发布,则为 v0.0.0)。

  • yyyymmddhhmmss
    提交时间戳。

  • commit
    Git 提交的哈希值前 12 位。

生成规则:
1.如果当前分支未打 tag,则伪版本基于 v0.0.0。

2.如果当前分支有 tag,则伪版本基于最新的 tag 版本号。

3.时间戳和提交哈希确保伪版本唯一。

优点:
1.能够引用尚未发布的模块代码。

2.精确定位到某个提交,适合调试和开发测试。

假设模块的最新提交哈希为 abc123456789,提交时间为 2024 年 1 月 1 日 12:00,则对应的伪版本可能为:

v1.5.3-20240101120000-abc123456789

在 go.mod 文件中配置:

require github.com/example/module v1.5.3-20240101120000-abc123456789

依赖配置

indirect

indirect 是 go.mod 文件中依赖项的一种标识,用于说明某个模块是间接依赖
间接依赖是指一个模块不是直接被你的代码引用,而是通过你的某个直接依赖引入的。

间接依赖在go.mod中的显示

require (
    github.com/example/moduleA v1.2.3
    github.com/example/moduleB v1.4.5 // indirect
)

其中 // indirect 标识 B 是通过直接依赖 A 间接引入的。

如果你的代码需要引用某个间接依赖模块的功能,则需要明确声明该依赖。在这种情况下:
Go 会将间接依赖升级为直接依赖(去掉 indirect 标识)。

作用:
使用 indirect 标识可以清晰区分模块的依赖关系,便于维护构建系统的稳定性和最小化依赖树。

间接依赖是 Go 自动计算并写入 go.mod 文件的。通常会在以下情况下生成:

  • 运行 go mod tidy 时,Go 会清理未使用的依赖并添加需要的间接依赖。
  • 运行 go get 安装或升级依赖时,间接依赖可能会显式写入 go.mod 文件。
incompatible

incompatible 标记表示模块的版本(v2+)与 Go 模块系统的版本规范不完全兼容。

  • 主要出现在旧版模块未更新模块路径的情况下。
  • 可以正常使用,但可能带来版本冲突和升级问题。

从 v2 开始,模块路径应包括版本号后缀(如 /v2)

GOPROXY

简介

Go Proxy 是一个模块代理服务器,用于加速和简化 Go 模块的分发。它位于 Go 工具和模块源代码之间,负责:

  • 缓存模块版本。
  • 提供稳定的依赖下载服务。
  • 避免开发者直接访问原始代码仓库(如 GitHub、GitLab)。
  • 通过 Proxy,Go 工具可以快速、安全地获取所需的模块依赖。

当你在 Go 环境中启用了模块(GO111MODULE=on),Go 工具会默认通过 https://proxy.golang.org 获取依赖。

优点
  • 提高模块获取速度。
  • 避免依赖源码仓库的可用性。
  • 缓存机制减少重复下载。
  • 支持验证模块的完整性和安全性。
缺点
  • 对私有模块支持有限(大部分 Proxy 不支持)。
  • 可能需要配置额外的代理服务(如国内用户访问 proxy.golang.org 不稳定)。

工具

go mod

go mod

  • init // 初始化,创建go.mod项目
  • download // 下载模块到本地缓存
  • tidy // 增加需要的依赖,删除不需要的依赖

示例

go mod init example.com/myproject
go mod tidy
go get example.com/mymodule@v1.2.3
go get

go get 是一个用于获取远程代码包的命令,支持以下操作:

  • 下载代码包到模块缓存中。
  • 更新项目的依赖版本。
  • 自动修改 go.mod 文件中的依赖项。
  • 在传统的 $GOPATH 模式下,获取包并放到 $GOPATH/src 下。

go get example.org/pkg

  • @update // 默认
  • @none // 删除依赖
  • @v1.1.2 // tag版本,语义版本
  • @23dfdd5 // 特定的commit
  • @master // 分支的最新commit
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值