likes
comments
collection
share

Go 插件每日推荐之 semver | Go 主题月semver 软件包提供了在 Go 语言中使用语义化版本的能力。 具

作者站长头像
站长
· 阅读数 39

大家好,我是 @洛竹

本文首发于 洛竹的官方网站

本文同步于公众号『洛竹早茶馆』,转载请联系作者。

创作不易,养成习惯,素质三连!

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。这两种比较方法之间有一些重要区别需要注意。

  1. 当使用诸如Compare,LessThan之类的函数比较两个版本时,它将遵循规范,并且在比较中始终包含预发行版本。 它将在 semver.org/#spec-item-… 规范比较部分中提供有效的答案
  2. 当使用约束检查进行检查或验证时,它将遵循一组不同的规则,这些规则对于诸如 npm/js 和 Rust/Cargo 之类的工具来说是很常见的。这包括如果范围中不包含预发行版本,则认为预发行版本无效。如果要使其包含预发行版本,一个简单的解决方案是在你的范围内包含 `-0'。
  3. 约束范围可以具有一些复杂的规则,包括 ^ 的缩写。有关这些内容的更多详细信息,请参见下面的选项。

两种方法或检查版本之间存在差异,因为 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 等价

比较中的通配符

xX* 可用作通配符。这适用于所有比较运算符。当在 = 运算符上使用时,它会退回到补丁程序级别比较(请参见下面的波浪号)。 例如,

  • 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
评论
请登录