Go 插件每日推荐之 semver | Go 主题月semver 软件包提供了在 Go 语言中使用语义化版本的能力。 具
大家好,我是 @洛竹
本文首发于 洛竹的官方网站
本文同步于公众号『洛竹早茶馆』,转载请联系作者。
创作不易,养成习惯,素质三连!
semver
软件包提供了在 Go 语言中使用语义化版本的能力。 具体来说,它提供了以下功能:
- 解析语义化版本
- 对语义化版本进行排序
- 检查语义版本是否符合一组约束
- (可选)使用
v
前缀
如果你正在寻找用于版本比较的命令行工具,请使用 vert 。
解析语义化版本
有两个函数可以解析语义版本。 StrictNewVersion
函数仅解析第 2 版语义化规范中有效的版本。NewVersion
函数试图将一个版本强制转换为语义版本并对其进行解析。 例如,如果有前导 v
或版本列出的所有 3 个部分(例如 v1.2
)都将尝试将其强制转换为有效的语义版本(例如 1.2.0)。在这两种情况下,都会返回 Version
对象,这个 Version
对象可以排序,比较并在约束中使用。
解析版本时,如果在解析版本时遇到问题,则会返回错误版本。 例如,
v, err := semver.NewVersion("1.2.3-beta.1+build345")
版本对象具有获取版本部分,将其与其他版本进行比较,将版本转换回字符串并获得原始字符串的方法。如果将语义版本强制转换为有效形式,则获取原始字符串很有用。
对语义化版本进行排序
可以使用标准库中的 sort
包对一组版本进行排序。例如,
raw := []string{"1.2.3", "1.0", "1.3", "2", "0.4.2",}
vs := make([]*semver.Version, len(raw))
for i, r := range raw {
v, err := semver.NewVersion(r)
if err != nil {
t.Errorf("Error parsing version: %s", err)
}
vs[i] = v
}
sort.Sort(semver.Collection(vs))
检查版本约束
有两种比较版本的方法。一种使用 Version
实例的比较方法,另一种使用 Constraints
。这两种比较方法之间有一些重要区别需要注意。
- 当使用诸如Compare,LessThan之类的函数比较两个版本时,它将遵循规范,并且在比较中始终包含预发行版本。 它将在 semver.org/#spec-item-… 规范比较部分中提供有效的答案
- 当使用约束检查进行检查或验证时,它将遵循一组不同的规则,这些规则对于诸如 npm/js 和 Rust/Cargo 之类的工具来说是很常见的。这包括如果范围中不包含预发行版本,则认为预发行版本无效。如果要使其包含预发行版本,一个简单的解决方案是在你的范围内包含 `-0'。
- 约束范围可以具有一些复杂的规则,包括
〜
和^
的缩写。有关这些内容的更多详细信息,请参见下面的选项。
两种方法或检查版本之间存在差异,因为 Version
上的比较方法遵循规范,而比较范围不属于规范的一部分。不同的软件包和工具自行决定了范围规则。这导致了差异。 例如,npm/js 和 Cargo/Rust 遵循相似的模式,而 PHP 的 ^
则具有不同的模式。该包中的比较功能遵循 npm/js 和 Cargo/Rust,因为使用该包的应用程序在其版本上遵循了相似的模式。
根据版本限制检查版本是包中功能最强大的部分之一。
c, err := semver.NewConstraint(">= 1.2.3")
if err != nil {
// 处理约束不可解析的情况。
}
v, err := semver.NewVersion("1.3")
if err != nil {
// 处理版本不能被解析的情况
}
// 检查版本是否符合约束,变量将是 `true`
a := c.Check(v)
基本比较
比较有两个要素。首先,比较字符串是由空格或逗号分隔的 AND
比较的列表。然后将它们用 ||
分隔。(OR)比较。 例如,> = 1.2 <3.0.0 ||> = 4.2.3
正在寻找一个大于或等于 1.2 且小于 3.0.0 或大于或等于 4.2.3 的比较。
基本比较为:
=
:equal (aliased to no operator)!=
:not equal>
:greater than<
:less than>=
:greater than or equal to<=
:less than or equal to
使用预发行版本
对于不熟悉它们的人来说,预发行版本用于稳定或普遍可用版本之前的软件发行。预发行版本的示例包括开发,alpha,beta 和发行候选版本。预发行版可能是诸如 1.2.3-beta.1
之类的版本,而稳定发行版可能是 1.2.3
。按照优先顺序,预发行版先于其关联的发行版。在此示例中,1.2.3-beta.1 < 1.2.3
。
根据语义版本规范,预发行版本可能与其发行版本不符合 API:
预发行版本表示该版本不稳定,可能无法满足其关联的正常版本所表示的预期兼容性要求。
使用不带预发行比较器的约束的 SemVer 比较将跳过预发行版本。例如,> = 1.2.3
将在查看发行版列表时跳过预发行版,而 > = 1.2.3-0
将判断并查找预发行版。
在示例比较中将 0
作为预发行版本的原因是,根据规范,预发行版本只能包含 ASCII 字母数字和连字符(以及 .
分隔符)。再次按照规范,以 ASCII 排序顺序进行排序。最低字符是 ASCII 排序顺序中的 0
(请参见ASCII表)
了解 ASCII 排序顺序很重要,因为 A-Z 在 a-z 之前。这意味着 > = 1.2.3-BETA
将返回 1.2.3-alpha
。你可能对区分大小写的期望并不适用于此。这是由于规范指定的 ASCII 排序顺序。
连字符范围比较
有多种方法可以处理范围,第一种是连字符范围。这些看起来像:
1.2 - 1.4.5
和>= 1.2 <= 1.4.5
等价2.3.4 - 4.5
和>= 2.3.4 <= 4.5
等价
比较中的通配符
x
、X
和 *
可用作通配符。这适用于所有比较运算符。当在 =
运算符上使用时,它会退回到补丁程序级别比较(请参见下面的波浪号)。 例如,
1.2.x
和>= 1.2.0, < 1.3.0
等价>= 1.2.x
和>= 1.2.0
等价<= 2.x
和< 3
等价*
和>= 0.0.0
等价
波浪范围比较(补丁)
如果指定了次要版本,则波浪号(〜
)比较运算符适用于补丁程序级别范围,如果缺少次要版本号,则主运算符级别会更改。 例如,
~1.2.3
和>= 1.2.3, < 1.3.0
等价~1
和>= 1, < 2
等价~2.3
和>= 2.3, < 2.4
等价~1.2.x
和>= 1.2.0, < 1.3.0
等价~1.x
和>= 1, < 2
等价
插入符范围比较(主要)
插入符号(^
)比较运算符用于在发生稳定(1.0.0)释放后进行主要级别更改。在 1.0.0 发行版之前,次要版本充当 API 稳定级别。当比较 API 版本时,这是很有用的,因为 API 发生了破坏性更新。 例如,
^1.2.3
和>= 1.2.3, < 2.0.0
等价^1.2.x
和>= 1.2.0, < 2.0.0
^2.3
和>= 2.3, < 3
等价^2.x
和>= 2.0.0, < 3
等价^0.2.3
和>=0.2.3 <0.3.0
等价^0.2
和>=0.2.0 <0.3.0
等价^0.0.3
和>=0.0.3 <0.0.4
等价^0.0
和>=0.0.0 <0.1.0
等价^0
和>=0.0.0 <1.0.0
等价
验证
除了针对约束测试版本之外,还可以针对约束验证版本。当验证失败时,将返回一条错误消息,其中包含版本不符合约束的原因。 例如,
c, err := semver.NewConstraint("<= 1.2.3, >= 1.4")
if err != nil {
// 处理约束不可解析的情况。
}
v, err := semver.NewVersion("1.3")
if err != nil {
// 处理版本不能被解析的情况
}
// 根据约束验证版本。
a, msgs := c.Validate(v)
// a 是 false
for _, m := range msgs {
fmt.Println(m)
// 循环读取的错误
// "1.3 is greater than 1.2.3"
// "1.3 is less than 1.4"
}
转载自:https://juejin.cn/post/6947139893789196318