Golang之 golang 钻石依赖 问题解决

Posted by 董江 on Monday, May 8, 2023

1. 基础规则:import兼容性规则

Go语言的import兼容性规则是指:

  • 如果一个旧包与新包共用相同的 import 路径,那么新包必须向后兼容旧包。

Go的开发者采用业界通用的semantic versioning作为版本标识符,它形如(major.minor.patch):

Go的兼容性规则希望开发者遵守如下守则:

  • 相同大版本,新包需要完全兼容旧包(通过诸如不删除弃用方法,不修改导出变量等手段)。例如:v1.3.1需要完全兼容v1.2.0
  • 不同大版本,允许存在不兼容改动。例如:v3.0.0v1.0.0允许声明不兼容的接口方法。
  • v0.0.0v1.0.0之间由于处于开发阶段,允许存在大量不兼容的行为,但需要开发者自己处理。

2. 钻石依赖 问题

钻石依赖问题: application直接依赖ABB依赖Cv1.0版本,A依赖Cv2.0版本,如果C的这两个版本是不兼容的。 这种情况下,无论是选择C v1.0还是C v2.0都无法得出正确的依赖构建

3. golang解决方案

3.1 Go的解决方案: 大版本major复合包含方法

go module解决方案:

由于C v1C v2属于C的不同大版本,因此当A引入C的时候,需要在import路径中加入/v2

因此go mod最终产生的依赖同时包括A、B、C v1和C v2,而不像go dep那样需要在C v1C v2之前做一个取舍。

3.2 minor最小版本兼容方法

application直接依赖ABDB依赖Cv1.2.8版本,A依赖Cv1.1.1版本,D依赖Cv1.3.8版本. 目前库中C中最新的个版本包:v1.5.8v2.1.2v3.0.11

最终选用了最小可用版本 v1.3.4

3.3 其他情况

3.3.1 依赖不带go.modlegacy Go

虽然Go module已经多年了,但Go社区仍然存在大量legacy的Go包尚未增加go.mod文件.

对于这一类引入:

dongjiang@MacBook Pro~/ $ go get k8s.io/kube-openapi   
go: downloading k8s.io/kube-openapi v0.0.0-20230501164219-8b0f38b5fd1f

这一类通过本地GOCACHE中保存,按v0.0.0-${time}-${md5sum}标识。 例如v0.0.0-20230501164219-8b0f38b5fd1f

可通过go get k8s.io/kube-openapi, 更新本地GOCAHCE

3.3.2 采用go module 关键字来解决以上问题

对于golang某些包未按照: 相同大版本,新包需要完全兼容旧包, 即:v1.3.1需要不兼容v1.2.0

可通过go module 特殊语义进行排他处理:

例子:


module github.com/kubeservice-stack/common

go 1.12

require github.com/other/common v1.0.2
require github.com/new/common/v2 v2.3.4
exclude github.com/old/common v1.2.3
replace github.com/bad/common v1.4.5 => github.com/good/common v1.4.5
retract [v1.9.0, v1.9.5]

关键语义:

  • require:require记录的内容生成go.sum
  • excludeexclude可以记录一个版本的黑名单,防止该版本被引用。
  • replacereplace可以用于替换一个依赖。
  • retractgo1.16新特性,可以用于包的开发者紧急撤回某个已知BUG的版本。

「如果这篇文章对你有用,请随意打赏」

Kubeservice博客

如果这篇文章对你有用,请随意打赏

使用微信扫描二维码完成支付