versions

package module
v0.0.0-...-1fd2178 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 22, 2025 License: MIT Imports: 12 Imported by: 0

README

Versions - Go语言版本号解析计算SDK

Go Tests Go Report Card GoDoc

Versions Logo

专业的 Go 语言版本号解析计算SDK - 轻松解析、比较、排序软件版本号

versions 是一个专为 Go 开发者设计的版本号解析计算SDK,专注于处理语义化版本号的解析、比较、排序和查询。它不是一个版本管理系统,而是一个帮助开发者处理版本号字符串的工具库。无论是依赖管理、API兼容性检查还是软件更新逻辑,都能高效完成版本号的计算需求。


📋 目录


✨ 特性

🔄 全面的版本号支持 支持标准语义化版本格式(如 1.2.3)和多种变体(如 v1.2.31.2.3-beta 等)
🧩 灵活的版本号解析 自动识别前缀、版本号和后缀,处理各种版本号格式
📊 版本号比较 基于标准语义化版本规则进行版本号比较,支持前缀和后缀处理
📦 版本号分组和排序 按主版本号、次版本号分组,并提供多种排序方式
🔍 版本号范围查询 支持查询指定版本号范围内的所有版本,带有灵活的包含/排除边界选项
📋 版本号可视化 提供文本方式展示版本号之间的层次关系,直观查看版本号组织结构
📁 文件支持 直接从文件中读取和处理版本号
🚀 无外部依赖 核心功能无需额外依赖,轻量快速

📦 安装

使用 go get 命令安装:

go get -u github.com/scagogogo/versions

🚀 快速开始

以下是一个简单的示例,展示如何使用 versions 库解析和比较版本号:

package main

import (
    "fmt"
    "github.com/scagogogo/versions"
)

func main() {
    // 创建版本对象
    v1 := versions.NewVersion("1.2.3")
    v2 := versions.NewVersion("v1.3.0")
    
    // 比较版本大小
    if v1.CompareTo(v2) < 0 {
        fmt.Printf("%s 小于 %s\n", v1.Raw, v2.Raw)
    }
    
    // 查看版本组成部分
    fmt.Printf("版本号数字: %v\n", v1.VersionNumbers)
    fmt.Printf("前缀: %s\n", v2.Prefix)  // 输出: "v"
    
    // 排序版本号
    versionList := []*versions.Version{
        versions.NewVersion("2.0.0"),
        versions.NewVersion("1.0.0"),
        versions.NewVersion("1.10.0"),
    }
    sortedVersions := versions.SortVersionSlice(versionList)
    for _, v := range sortedVersions {
        fmt.Println(v.Raw)  // 输出: 1.0.0, 1.10.0, 2.0.0
    }
}
查看输出结果
1.2.3 小于 v1.3.0
版本号数字: [1 2 3]
前缀: v
1.0.0
1.10.0
2.0.0

📚 详细文档

数据类型和常量
类型 描述
Version 表示一个版本号,包含原始字符串、版本号数字、前缀、后缀和发布时间
VersionNumbers 整数切片,表示版本号中的数字部分
VersionPrefix 字符串,表示版本号数字部分之前的前缀
VersionSuffix 字符串,表示版本号数字部分之后的后缀
ContainsPolicy 用于控制版本查询时的包含策略(包含、不包含)
VersionGroup 版本组,包含相同主版本号的一组版本
SortedVersionGroups 有序的版本组集合,便于范围查询
主要函数
版本解析与创建
// 创建版本对象
version := versions.NewVersion("1.2.3")

// 带错误检查的版本创建
version, err := versions.NewVersionE("1.2.3")
if err != nil {
    log.Fatal(err)
}
从文件读取版本
// 读取版本号对象
versions, err := versions.ReadVersionsFromFile("path/to/versions.txt")
if err != nil {
    log.Fatal(err)
}

// 读取版本号字符串
versionStrings, err := versions.ReadVersionsStringFromFile("path/to/versions.txt")
if err != nil {
    log.Fatal(err)
}
版本分组与排序
// 版本分组
groupedVersions := versions.Group(versionList)

// 字符串版本排序
sortedStrings := versions.SortVersionStringSlice(versionStrings)

// 版本对象排序
sortedVersions := versions.SortVersionSlice(versionList)
版本范围查询
// 创建有序版本组
sortedGroups := versions.NewSortedVersionGroups(versionList)

// 定义查询范围和包含策略
startVersion := versions.NewVersion("1.0.0")
endVersion := versions.NewVersion("2.0.0")
startTuple := tuple.New2[*versions.Version, versions.ContainsPolicy](
    startVersion, versions.ContainsPolicyYes) // 包含起始版本
endTuple := tuple.New2[*versions.Version, versions.ContainsPolicy](
    endVersion, versions.ContainsPolicyNo)   // 不包含结束版本

// 执行范围查询
rangeResult := sortedGroups.QueryRange(startTuple, endTuple)
版本可视化
// 可视化所有版本(每组显示最多5个版本)
versions.VisualizeVersions(versionList, os.Stdout, 5)

// 可视化版本组层次结构
versions.VisualizeVersionGroups(versionList, os.Stdout)

可视化输出示例:

版本总数: 15
版本组数: 3

┌─ 版本组: 1.0 (3个版本)
├── 1.0.0 (发布时间: 2020-01-01)
├── 1.0.1 (发布时间: 2020-02-01)
└── 1.0.2 (发布时间: 2020-03-01)

┌─ 版本组: 2.0 (4个版本)
├── 2.0.0 (发布时间: 2021-01-01)
├── 2.0.1 (发布时间: 2021-02-01)
├── 2.0.2 (发布时间: 2021-03-01)
└── ...还有1个版本未显示

🧩 完整API文档

核心类型与功能详解

Version 类型
结构定义
type Version struct {
    // 原始版本号字符串
    Raw string
    
    // 版本发布时间
    PublicTime time.Time
    
    // 版本号数字部分,例如 1.2.3 中的 [1,2,3]
    VersionNumbers VersionNumbers
    
    // 版本号前缀,例如 v1.2.3 中的 "v"
    Prefix VersionPrefix
    
    // 版本号后缀,例如 1.2.3-beta 中的 "-beta"
    Suffix VersionSuffix
}
NewVersion - 创建版本号对象
func NewVersion(versionString string) *Version

参数:

  • versionString string: 版本号字符串,如 "1.2.3", "v1.0.0-beta" 等

返回值:

  • *Version: 解析后的版本对象

处理逻辑:

  1. 自动识别版本号前缀(如 "v")
  2. 解析版本号数字部分(如 "1.2.3" 中的 [1,2,3])
  3. 提取版本号后缀(如 "-beta", "-rc1" 等)
  4. 创建完整的版本对象

特性:

  • 支持任意数量的版本号段(如 "1.2.3.4.5")
  • 自动处理前导零(如 "1.02.003" 被解析为 [1,2,3])
  • 不会因解析错误而抛出异常,解析失败时会返回空版本号

示例:

version := versions.NewVersion("v1.2.3-rc1")
fmt.Printf("前缀: %s, 版本号: %v, 后缀: %s\n", 
    version.Prefix, version.VersionNumbers, version.Suffix)
// 输出: 前缀: v, 版本号: [1 2 3], 后缀: -rc1

// 处理非标准版本号
custom := versions.NewVersion("release-1.0-final")
fmt.Printf("前缀: %s, 版本号: %v, 后缀: %s\n", 
    custom.Prefix, custom.VersionNumbers, custom.Suffix)
// 输出: 前缀: release-, 版本号: [1 0], 后缀: -final
NewVersionE - 创建版本号对象(带错误返回)
func NewVersionE(versionString string) (*Version, error)

参数:

  • versionString string: 版本号字符串

返回值:

  • *Version: 解析后的版本对象
  • error: 解析过程中可能发生的错误,如:
    • 无法识别的版本号格式
    • 版本号中不包含数字部分
    • 版本号数字部分解析失败

错误处理:

  • 当版本号字符串为空时,返回 ErrEmptyVersionString 错误
  • 当版本号中没有找到数字时,返回 ErrNoVersionNumbersFound 错误
  • 当无法识别版本号格式时,返回 ErrInvalidVersionFormat 错误

示例:

version, err := versions.NewVersionE("v1.2.3-rc1")
if err != nil {
    log.Fatalf("版本号解析失败: %v", err)
}

// 错误处理示例
version, err = versions.NewVersionE("")
if err != nil {
    fmt.Printf("空版本号错误: %v\n", err) 
    // 输出: 空版本号错误: empty version string
}

version, err = versions.NewVersionE("no-numbers")
if err != nil {
    fmt.Printf("无数字版本号错误: %v\n", err)
    // 输出: 无数字版本号错误: no version numbers found
}
IsValid - 检查版本号是否有效
func (v *Version) IsValid() bool

返回值:

  • bool: 版本号是否有效,必须至少包含一个版本数字

验证标准:

  • 版本号对象不能为 nil
  • VersionNumbers 字段必须至少包含一个数字
  • Raw 字段不能为空字符串

使用场景:

  • 过滤无效的版本号对象
  • 验证用户输入的版本号是否有效
  • 在批量处理版本号前进行有效性检查

示例:

version := versions.NewVersion("v1.2.3")
if version.IsValid() {
    fmt.Println("版本号有效") // 会执行这行
}

emptyVersion := versions.NewVersion("")
if !emptyVersion.IsValid() {
    fmt.Println("空版本号无效") // 会执行这行
}

invalidVersion := versions.NewVersion("no-numbers")
if !invalidVersion.IsValid() {
    fmt.Println("无数字版本号无效") // 会执行这行
}
CompareTo - 比较两个版本号
func (v *Version) CompareTo(other *Version) int

参数:

  • other *Version: 要比较的另一个版本对象

返回值:

  • int:
    • 小于0: 当前版本小于 other 版本
    • 等于0: 两个版本相等
    • 大于0: 当前版本大于 other 版本

比较规则:

  1. 首先比较版本号数字部分,按位比较,长度不同时短的版本号在缺失位置视为0
  2. 如果版本号数字部分相同,则比较前缀
  3. 如果前缀也相同,则比较后缀
  4. 如果前缀和后缀都相同,则比较发布时间
  5. 如果以上都相同,则认为两个版本相等

兼容性说明:

  • 能正确处理数字部分不同长度的版本号比较(如 "1.0" 和 "1.0.0")
  • 前缀比较区分大小写(如 "v1.0" 和 "V1.0" 被视为不同)
  • 后缀比较遵循预发布版本规则(如 "-alpha" < "-beta" < "-rc" < 正式版)

示例:

v1 := versions.NewVersion("1.2.3")
v2 := versions.NewVersion("1.3.0")
result := v1.CompareTo(v2)
if result < 0 {
    fmt.Printf("%s 小于 %s\n", v1.Raw, v2.Raw) // 会执行这行
}

// 比较相同数字部分但有不同前后缀的版本
v3 := versions.NewVersion("v1.0.0")
v4 := versions.NewVersion("1.0.0-beta")
if v4.CompareTo(v3) < 0 {
    fmt.Println("预发布版本小于正式版本") // 会执行这行
}

// 比较发布时间
v5 := versions.NewVersion("1.0.0")
v6 := versions.NewVersion("1.0.0")
v5.PublicTime = time.Date(2020, 1, 1, 0, 0, 0, 0, time.UTC)
v6.PublicTime = time.Date(2021, 1, 1, 0, 0, 0, 0, time.UTC)
if v5.CompareTo(v6) < 0 {
    fmt.Println("早期发布的版本小于晚期发布的版本") // 会执行这行
}
String - 获取版本号字符串表示
func (v *Version) String() string

返回值:

  • string: 版本号的字符串表示,通常等同于原始版本号

行为说明:

  • 如果 Raw 字段不为空,则直接返回 Raw 字段
  • 如果 Raw 字段为空,则根据版本号各组成部分拼接成字符串返回
  • 返回的字符串格式为:前缀 + 版本号数字(以点分隔) + 后缀

使用场景:

  • 在日志或输出中显示版本号
  • 将版本对象转换回字符串用于存储或传输
  • 在比较后选择特定版本时获取其字符串表示

示例:

version := versions.NewVersion("v1.2.3")
fmt.Println(version.String()) // 输出: v1.2.3

// 使用String()方法在日志中显示版本信息
log.Printf("当前使用的版本: %s", version)

// 通过比较后选择最大版本并显示
v1 := versions.NewVersion("1.0.0")
v2 := versions.NewVersion("2.0.0")
var latestVersion *versions.Version
if v1.CompareTo(v2) > 0 {
    latestVersion = v1
} else {
    latestVersion = v2
}
fmt.Printf("最新版本: %s\n", latestVersion) // 输出: 最新版本: 2.0.0
VersionNumbers 类型
结构定义与方法
// VersionNumbers 是整数切片,表示版本号的数字部分
type VersionNumbers []int

// 获取主版本号
func (v VersionNumbers) MajorVersion() int

// 获取次版本号
func (v VersionNumbers) MinorVersion() int

// 获取修订版本号
func (v VersionNumbers) PatchVersion() int

// 比较两个版本号数字部分
func (v VersionNumbers) CompareTo(other VersionNumbers) int

详细方法说明:

MajorVersion(): 获取主版本号(第一个数字)

  • 返回值: int - 版本号的第一个数字
  • 行为: 如果版本号为空,返回0;否则返回第一个数字
  • 用途: 用于识别不兼容API变更的主版本

MinorVersion(): 获取次版本号(第二个数字)

  • 返回值: int - 版本号的第二个数字
  • 行为: 如果版本号不足两段,返回0;否则返回第二个数字
  • 用途: 用于识别向后兼容的功能性变更

PatchVersion(): 获取修订版本号(第三个数字)

  • 返回值: int - 版本号的第三个数字
  • 行为: 如果版本号不足三段,返回0;否则返回第三个数字
  • 用途: 用于识别向后兼容的问题修复

CompareTo(other VersionNumbers): 比较两个版本号数字部分

  • 参数: other VersionNumbers - 要比较的另一个版本号数字
  • 返回值: int - 小于0表示当前版本小,等于0表示相等,大于0表示当前版本大
  • 比较规则:
    1. 从左到右逐位比较,高位优先
    2. 对于长度不同的版本号,缺失部分视为0(如1.0和1.0.0被视为相等)
    3. 数字大的版本号大(如1.2.0大于1.1.9)

高级用法:

  • 可以处理任意长度的版本号(不限于语义化版本的三段式)
  • 支持零值安全比较(空的VersionNumbers被视为[0])
  • 可直接访问底层切片获取特定位置的版本号数字

示例:

version := versions.NewVersion("1.2.3")
major := version.VersionNumbers.MajorVersion() // 返回 1
minor := version.VersionNumbers.MinorVersion() // 返回 2
patch := version.VersionNumbers.PatchVersion() // 返回 3

// 比较版本号数字部分
v1Numbers := versions.NewVersion("1.2.0").VersionNumbers
v2Numbers := versions.NewVersion("1.2.3").VersionNumbers
if v1Numbers.CompareTo(v2Numbers) < 0 {
    fmt.Println("1.2.0 的数字部分小于 1.2.3") // 会执行这行
}

// 处理超过三段的版本号
longVersion := versions.NewVersion("1.2.3.4.5")
fmt.Printf("第5段版本号: %d\n", longVersion.VersionNumbers[4]) // 输出: 第5段版本号: 5

// 根据版本号数字部分生成分支名
version := versions.NewVersion("2.5.1")
branchName := fmt.Sprintf("release/%d.%d.x", 
    version.VersionNumbers.MajorVersion(),
    version.VersionNumbers.MinorVersion())
fmt.Println(branchName) // 输出: release/2.5.x
VersionPrefix 类型
结构定义与方法
// VersionPrefix 是字符串,表示版本号前缀
type VersionPrefix string

// 检查前缀是否为空
func (v VersionPrefix) IsEmpty() bool

// 比较两个前缀
func (v VersionPrefix) CompareTo(other VersionPrefix) int

详细方法说明:

IsEmpty(): 检查前缀是否为空

  • 返回值: bool - 前缀是否为空字符串
  • 行为: 当前缀为空字符串时返回true,否则返回false
  • 用途: 判断版本号是否有前缀,通常用于决定是否需要特殊处理

CompareTo(other VersionPrefix): 比较两个前缀

  • 参数: other VersionPrefix - 要比较的另一个前缀
  • 返回值: int - 小于0表示当前前缀字典序小,等于0表示相等,大于0表示当前前缀字典序大
  • 比较规则:
    1. 使用字符串字典序比较
    2. 区分大小写(如"v"和"V"被视为不同)
    3. 空前缀小于任何非空前缀

常见前缀类型:

  • v - 常见的版本号前缀,如 "v1.2.3"
  • version- - 一些项目使用的冗长前缀
  • release- - 表示发布版本的前缀
  • Ver - 带大写字母的变体

使用场景:

  • 识别版本号的类型或来源
  • 保持与特定工具或生态系统的兼容性
  • 在显示时维持一致的格式

示例:

version := versions.NewVersion("v1.2.3")
if !version.Prefix.IsEmpty() {
    fmt.Printf("版本前缀: %s\n", version.Prefix) // 输出: 版本前缀: v
}

// 比较前缀
v1 := versions.NewVersion("v1.0.0")
v2 := versions.NewVersion("release-1.0.0")
if v1.Prefix.CompareTo(v2.Prefix) < 0 {
    fmt.Println("v 前缀字典序小于 release- 前缀") // 不会执行,因为 "v" 字典序大于 "release-"
} else {
    fmt.Println("release- 前缀字典序小于 v 前缀") // 会执行这行
}

// 去除前缀获取纯版本号
version := versions.NewVersion("v2.0.1")
pureVersionStr := strings.TrimPrefix(version.Raw, string(version.Prefix))
fmt.Println(pureVersionStr) // 输出: 2.0.1
VersionSuffix 类型
结构定义与方法
// VersionSuffix 是字符串,表示版本号后缀
type VersionSuffix string

// 检查后缀是否为空
func (v VersionSuffix) IsEmpty() bool

// 比较两个后缀
func (v VersionSuffix) CompareTo(other VersionSuffix) int

详细方法说明:

IsEmpty(): 检查后缀是否为空

  • 返回值: bool - 后缀是否为空字符串
  • 行为: 当后缀为空字符串时返回true,否则返回false
  • 用途: 判断是否为预发布版本,通常正式版本没有后缀

CompareTo(other VersionSuffix): 比较两个后缀

  • 参数: other VersionSuffix - 要比较的另一个后缀
  • 返回值: int - 小于0表示当前后缀优先级低,等于0表示相等,大于0表示当前后缀优先级高
  • 比较规则:
    1. 空后缀大于任何非空后缀(正式版大于预发布版)
    2. 基于预发布版本通用优先级规则
    3. 对于相同类型的后缀,进一步按字符串比较

常见后缀类型和优先级(从低到高):

  1. -dev, -alpha, -a - 开发预览版/测试版
  2. -beta, -b - 测试版
  3. -milestone, -m - 里程碑版本
  4. -rc, -pre - 发布候选版
  5. 无后缀 - 正式发布版

使用场景:

  • 标识预发布版本
  • 确定版本稳定性和发布阶段
  • 控制客户端更新策略(可能排除某些后缀类型)

示例:

version := versions.NewVersion("1.2.3-beta")
if !version.Suffix.IsEmpty() {
    fmt.Printf("版本后缀: %s\n", version.Suffix) // 输出: 版本后缀: -beta
}

// 比较后缀优先级
v1 := versions.NewVersion("1.0.0-alpha")
v2 := versions.NewVersion("1.0.0-beta")
v3 := versions.NewVersion("1.0.0-rc1")
v4 := versions.NewVersion("1.0.0")

// 优先级: alpha < beta < rc < 正式版
if v1.Suffix.CompareTo(v2.Suffix) < 0 {
    fmt.Println("alpha 后缀优先级低于 beta 后缀") // 会执行这行
}
if v2.Suffix.CompareTo(v3.Suffix) < 0 {
    fmt.Println("beta 后缀优先级低于 rc 后缀") // 会执行这行
}
if v3.Suffix.CompareTo(v4.Suffix) < 0 {
    fmt.Println("rc 后缀优先级低于无后缀(正式版)") // 会执行这行
}

// 确定版本是否为预发布版本
if !version.Suffix.IsEmpty() {
    fmt.Println("这是预发布版本,不推荐用于生产环境")
}
ContainsPolicy 类型
定义与常量
// ContainsPolicy 用于控制版本范围查询时是否包含边界版本
type ContainsPolicy int

const (
    // 未指定包含策略
    ContainsPolicyNone ContainsPolicy = iota
    
    // 包含边界版本
    ContainsPolicyYes
    
    // 不包含边界版本
    ContainsPolicyNo
)

详细说明:

ContainsPolicy 是一个枚举类型,用于在版本范围查询中指定是否包含边界版本。

常量值:

ContainsPolicyNone (0):

  • 含义: 未指定包含策略,通常使用默认策略
  • 默认行为: 在大多数上下文中等同于 ContainsPolicyYes
  • 使用场景: 当不关心边界包含性或希望使用系统默认行为时

ContainsPolicyYes (1):

  • 含义: 包含边界版本
  • 符号表示: 对应数学符号中的闭区间 [, ]
  • 使用场景: 当查询需要包含指定的起始或结束版本时

ContainsPolicyNo (2):

  • 含义: 不包含边界版本
  • 符号表示: 对应数学符号中的开区间 (, )
  • 使用场景: 当查询需要排除指定的起始或结束版本时

行为举例:

  • [1.0.0, 2.0.0]: 包含1.0.0和2.0.0及其间的所有版本
  • (1.0.0, 2.0.0): 不包含1.0.0和2.0.0,只包含其间的版本
  • [1.0.0, 2.0.0): 包含1.0.0但不包含2.0.0
  • (1.0.0, 2.0.0]: 不包含1.0.0但包含2.0.0

在实际代码中的应用:

  • 与版本范围查询函数配合使用
  • 用于构建版本兼容性条件
  • 实现依赖规范中定义的版本范围

示例:

// 创建版本
v1 := versions.NewVersion("1.0.0")
v2 := versions.NewVersion("2.0.0")

// 创建版本范围查询条件
startWithInclude := tuple.New2[*versions.Version, versions.ContainsPolicy](
    v1, versions.ContainsPolicyYes) // 包含起始版本,相当于 [1.0.0
endWithExclude := tuple.New2[*versions.Version, versions.ContainsPolicy](
    v2, versions.ContainsPolicyNo)  // 不包含结束版本,相当于 2.0.0)

// 使用版本组执行范围查询(模拟 [1.0.0, 2.0.0) 范围)
result := sortedGroups.QueryRange(startWithInclude, endWithExclude)

// 在日志中显示查询范围
fmt.Printf("查询版本范围: %s%s, %s%s\n",
    inclusionSymbol(startWithInclude.V2), startWithInclude.V1.Raw,
    endWithExclude.V1.Raw, exclusionSymbol(endWithExclude.V2))
// 输出: 查询版本范围: [1.0.0, 2.0.0)

// 辅助函数示例
func inclusionSymbol(policy versions.ContainsPolicy) string {
    if policy == versions.ContainsPolicyNo {
        return "("
    }
    return "["
}

func exclusionSymbol(policy versions.ContainsPolicy) string {
    if policy == versions.ContainsPolicyNo {
        return ")"
    }
    return "]"
}
VersionGroup 类型
结构定义与方法
// VersionGroup 表示具有相同主版本号的一组版本
type VersionGroup struct {
    // ...内部字段
}

// 创建新的版本组
func NewVersionGroup(id string) *VersionGroup

// 添加版本到组中
func (g *VersionGroup) Add(version *Version)

// 检查组是否包含某个版本
func (g *VersionGroup) Contains(version *Version) bool

// 获取组ID
func (g *VersionGroup) ID() string

// 获取组中的所有版本
func (g *VersionGroup) Versions() []*Version

// 获取组中版本的数量
func (g *VersionGroup) Count() int

// 按版本号排序组内的版本
func (g *VersionGroup) SortVersions() []*Version

// 查询范围内的版本
func (g *VersionGroup) QueryRangeVersions(start, end *Version) []*Version

详细方法说明:

NewVersionGroup(id string): 创建新的版本组

  • 参数: id string - 组的标识符,通常是主版本号
  • 返回值: *VersionGroup - 新创建的版本组对象
  • 行为: 初始化一个空的版本组,带有指定的ID
  • 用途: 手动创建版本组,用于后续添加版本

Add(version *Version): 添加版本到组中

  • 参数: version *Version - 要添加的版本对象
  • 行为: 将版本添加到组中,如果版本已存在则不重复添加
  • 注意: 不会验证版本的主版本号是否与组ID匹配
  • 用途: 向版本组添加新版本

Contains(version *Version) bool: 检查组是否包含某个版本

  • 参数: version *Version - 要检查的版本对象
  • 返回值: bool - 组中是否包含该版本
  • 比较方式: 使用版本的 Raw 字符串进行比较
  • 用途: 确定特定版本是否已在组中

ID() string: 获取组ID

  • 返回值: string - 组的标识符
  • 行为: 返回创建组时指定的ID
  • 用途: 识别版本组,通常等同于主版本号

Versions() []*Version: 获取组中的所有版本

  • 返回值: []*Version - 组中所有版本的切片
  • 行为: 返回版本组内部存储的所有版本对象
  • 注意: 返回的切片不保证有特定顺序
  • 用途: 获取组内所有版本进行遍历或处理

Count() int: 获取组中版本的数量

  • 返回值: int - 组中版本的数量
  • 行为: 返回组中包含的版本对象数量
  • 用途: 快速获取组大小,无需遍历版本

SortVersions() []*Version: 按版本号排序组内的版本

  • 返回值: []*Version - 排序后的版本对象切片
  • 排序规则: 使用 Version.CompareTo 方法比较,按版本号从小到大排序
  • 用途: 获取组内按序排列的版本列表

QueryRangeVersions(start, end *Version) []*Version: 查询范围内的版本

  • 参数:
    • start *Version - 范围起始版本
    • end *Version - 范围结束版本
  • 返回值: []*Version - 符合范围条件的版本对象切片
  • 行为: 返回组内版本号在 start 和 end 之间的所有版本(包含 start 和 end)
  • 注意: 返回的结果已按版本号排序
  • 用途: 获取特定版本范围内的所有版本

版本组常见使用场景:

  • 按主版本号对版本进行分组管理
  • 在UI中展示按主版本组织的版本列表
  • 对特定主版本内的版本执行范围查询
  • 获取特定主版本的最新版本或稳定版本

示例:

// 创建版本组
group := versions.NewVersionGroup("1")

// 添加版本
group.Add(versions.NewVersion("1.0.0"))
group.Add(versions.NewVersion("1.1.0"))
group.Add(versions.NewVersion("1.2.0"))

// 获取组内所有版本
allVersions := group.Versions()
fmt.Printf("版本组 %s 包含 %d 个版本\n", group.ID(), group.Count())
// 输出: 版本组 1 包含 3 个版本

// 排序组内版本
sortedVersions := group.SortVersions()
fmt.Println("排序后的版本:")
for i, v := range sortedVersions {
    fmt.Printf("%d. %s\n", i+1, v.Raw)
}
// 输出:
// 排序后的版本:
// 1. 1.0.0
// 2. 1.1.0
// 3. 1.2.0

// 检查版本是否在组中
v := versions.NewVersion("1.1.0")
if group.Contains(v) {
    fmt.Printf("版本组 %s 包含版本 %s\n", group.ID(), v.Raw)
    // 输出: 版本组 1 包含版本 1.1.0
}

// 范围查询
start := versions.NewVersion("1.0.5")
end := versions.NewVersion("1.1.5")
rangeVersions := group.QueryRangeVersions(start, end)
fmt.Printf("范围 %s 到 %s 内的版本数: %d\n", start.Raw, end.Raw, len(rangeVersions))
// 输出: 范围 1.0.5 到 1.1.5 内的版本数: 1 (只有1.1.0在这个范围内)

// 获取组内最新版本
latestVersion := group.SortVersions()[group.Count()-1]
fmt.Printf("版本组 %s 中的最新版本: %s\n", group.ID(), latestVersion.Raw)
// 输出: 版本组 1 中的最新版本: 1.2.0
SortedVersionGroups 类型
结构定义与方法
// SortedVersionGroups 表示一组有序的版本组
type SortedVersionGroups struct {
    // ...内部字段
}

// 创建新的有序版本组
func NewSortedVersionGroups(versions []*Version) *SortedVersionGroups

// 获取所有版本组ID
func (s *SortedVersionGroups) GroupIDs() []string

// 查询指定范围内的版本
func (s *SortedVersionGroups) QueryRange(
    start *tuple.Tuple2[*Version, ContainsPolicy],
    end *tuple.Tuple2[*Version, ContainsPolicy],
) []*Version

详细方法说明:

NewSortedVersionGroups(versions []*Version): 创建新的有序版本组

  • 参数: versions []*Version - 版本对象切片
  • 返回值: *SortedVersionGroups - 有序版本组对象
  • 行为:
    1. 将版本按主版本号分组创建 VersionGroup
    2. 对各组内版本进行排序
    3. 将版本组按组ID排序
  • 用途: 构建用于高效查询和遍历的有序版本结构

GroupIDs() []string: 获取所有版本组ID

  • 返回值: []string - 所有版本组ID的切片
  • 行为: 返回已排序的版本组ID列表(通常是主版本号)
  • 顺序: 按字符串顺序排序,数字ID会考虑数值大小
  • 用途:
    • 获取所有可用的主版本号
    • 在UI中创建版本选择器
    • 按主版本顺序遍历版本

QueryRange(...) []*Version: 查询指定范围内的版本

  • 参数:
    • start *tuple.Tuple2[*Version, ContainsPolicy] - 起始版本及其包含策略
    • end *tuple.Tuple2[*Version, ContainsPolicy] - 结束版本及其包含策略
  • 返回值: []*Version - 符合范围条件的版本对象切片
  • 行为:
    1. 确定范围覆盖的版本组
    2. 在每个相关组内执行范围查询
    3. 合并结果并按版本顺序排序
  • 特点:
    • 支持跨版本组的范围查询
    • 考虑包含策略确定边界处理
    • 结果按版本顺序排序
  • 用途:
    • 实现版本选择器中的范围过滤
    • 查找指定范围内的兼容版本
    • 获取特定范围内的版本更新

使用场景:

  • 在前端UI中展示分层的版本选择器
  • 实现符合语义化版本规范的版本范围查询
  • 处理大量版本时提供高效的版本过滤和分组显示

性能特点:

  • 初始化时完成分组和排序,查询操作高效
  • 范围查询利用排序特性,具有对数级时间复杂度
  • 适合处理大规模版本集合,并支持频繁的查询操作

示例:

// 创建测试版本列表
versionList := []*versions.Version{
    versions.NewVersion("1.0.0"),
    versions.NewVersion("1.1.0"),
    versions.NewVersion("2.0.0"),
    versions.NewVersion("2.1.0"),
    versions.NewVersion("3.0.0"),
}

// 创建有序版本组
sortedGroups := versions.NewSortedVersionGroups(versionList)

// 获取所有组ID
groupIDs := sortedGroups.GroupIDs()
fmt.Printf("共有 %d 个版本组: %v\n", len(groupIDs), groupIDs)
// 输出: 共有 3 个版本组: [1 2 3]

// 执行范围查询:获取1.0.0(包含)到2.0.0(不包含)之间的所有版本
startVersion := versions.NewVersion("1.0.0")
endVersion := versions.NewVersion("2.0.0")

// 创建包含策略元组
startTuple := tuple.New2[*versions.Version, versions.ContainsPolicy](
    startVersion, versions.ContainsPolicyYes) // 包含起始版本
endTuple := tuple.New2[*versions.Version, versions.ContainsPolicy](
    endVersion, versions.ContainsPolicyNo)    // 不包含结束版本
    
// 执行查询
result := sortedGroups.QueryRange(startTuple, endTuple)
fmt.Printf("查询结果包含 %d 个版本\n", len(result))
// 输出: 查询结果包含 2 个版本 (1.0.0, 1.1.0)

// 打印查询结果
for i, v := range result {
    fmt.Printf("%d. %s\n", i+1, v.Raw)
}
// 输出:
// 1. 1.0.0
// 2. 1.1.0

// 另一个范围查询示例:获取所有大于等于2.0.0的版本
laterVersionQuery := sortedGroups.QueryRange(
    tuple.New2[*versions.Version, versions.ContainsPolicy](
        versions.NewVersion("2.0.0"), 
        versions.ContainsPolicyYes),
    tuple.New2[*versions.Version, versions.ContainsPolicy](
        nil, versions.ContainsPolicyNone), // nil表示不设上限
)
fmt.Printf("2.0.0及以后的版本共有 %d 个\n", len(laterVersionQuery))
// 输出: 2.0.0及以后的版本共有 3 个 (2.0.0, 2.1.0, 3.0.0)
文件操作函数
从文件读取版本号
// 读取文件中的版本号字符串
func ReadVersionsStringFromFile(filepath string) ([]string, error)

// 读取并解析文件中的版本号
func ReadVersionsFromFile(filepath string) ([]*Version, error)

详细函数说明:

ReadVersionsStringFromFile(filepath string): 读取文件中的版本号字符串

  • 参数: filepath string - 文件路径
  • 返回值:
    • []string - 版本号字符串切片
    • error - 读取过程中可能发生的错误
  • 行为:
    1. 打开并读取指定文件
    2. 按行分割文件内容
    3. 去除每行首尾空白字符
    4. 过滤空行和注释行(以#开头)
    5. 返回有效的版本号字符串行
  • 错误处理:
    • 文件不存在:返回 os.ErrNotExist
    • 权限问题:返回相应的文件系统错误
    • 读取失败:返回 io.EOF 或其他I/O错误
  • 用途: 读取版本列表文件,获取原始版本号字符串

ReadVersionsFromFile(filepath string): 读取并解析文件中的版本号

  • 参数: filepath string - 文件路径
  • 返回值:
    • []*Version - 版本对象切片
    • error - 读取或解析过程中可能发生的错误
  • 行为:
    1. 调用 ReadVersionsStringFromFile 获取版本号字符串
    2. 对每个字符串调用 NewVersion 创建版本对象
    3. 返回创建的版本对象切片
  • 错误处理:
    • 继承 ReadVersionsStringFromFile 的所有错误
    • 不会因版本解析失败而返回错误(使用 NewVersion 而非 NewVersionE)
  • 用途: 一次性读取并解析版本列表文件

文件格式要求:

  • 每行一个版本号
  • 支持空行(会被忽略)
  • 支持注释行(以#开头,会被忽略)
  • 行首尾的空白字符会被自动移除

性能考虑:

  • 对于大文件,考虑使用缓冲读取
  • 如需处理无效版本,应在读取后手动过滤
  • 读取后可考虑缓存结果,避免频繁IO操作

示例:

// 从文件读取版本号字符串
versionStrings, err := versions.ReadVersionsStringFromFile("versions.txt")
if err != nil {
    log.Fatalf("读取版本号失败: %v", err)
}
fmt.Printf("共读取 %d 个版本号字符串\n", len(versionStrings))

// 从文件读取并解析版本号
versionObjects, err := versions.ReadVersionsFromFile("versions.txt")
if err != nil {
    log.Fatalf("解析版本号失败: %v", err)
}
fmt.Printf("共解析 %d 个版本号对象\n", len(versionObjects))

// 版本号文件示例 (versions.txt):
// # 稳定版本
// 1.0.0
// 1.0.1
// 1.0.2
// 
// # 预发布版本
// 1.1.0-alpha
// 1.1.0-beta
// 1.1.0-rc1

// 高级应用:读取并分组版本
versionObjects, err := versions.ReadVersionsFromFile("versions.txt")
if err != nil {
    log.Fatalf("读取版本号失败: %v", err)
}
sortedGroups := versions.NewSortedVersionGroups(versionObjects)
fmt.Printf("共读取 %d 个版本,分为 %d 个版本组\n", 
    len(versionObjects), len(sortedGroups.GroupIDs()))

// 过滤无效版本
validVersions := make([]*versions.Version, 0)
for _, v := range versionObjects {
    if v.IsValid() {
        validVersions = append(validVersions, v)
    } else {
        fmt.Printf("忽略无效版本: %s\n", v.Raw)
    }
}
fmt.Printf("有效版本数: %d\n", len(validVersions))
排序函数
版本排序函数
// 对版本字符串切片进行排序
func SortVersionStringSlice(versionStringSlice []string) []string

// 对版本对象切片进行排序
func SortVersionSlice(versions []*Version) []*Version

详细函数说明:

SortVersionStringSlice(versionStringSlice []string): 对版本字符串切片进行排序

  • 参数: versionStringSlice []string - 要排序的版本号字符串切片
  • 返回值: []string - 排序后的版本号字符串切片
  • 行为:
    1. 将字符串转换为版本对象
    2. 对版本对象进行排序
    3. 将排序后的版本对象转回字符串
  • 排序规则: 基于 Version.CompareTo 方法比较
  • 处理无效版本:
    • 无效或无法解析的版本会出现在结果中
    • 无效版本之间的顺序取决于其原始字符串
  • 用途: 直接对版本号字符串进行排序,无需手动创建版本对象

SortVersionSlice(versions []*Version): 对版本对象切片进行排序

  • 参数: versions []*Version - 要排序的版本对象切片
  • 返回值: []*Version - 排序后的版本对象切片
  • 行为: 对输入的版本对象切片进行原地排序
  • 排序规则: 基于 Version.CompareTo 方法比较
  • 处理无效版本:
    • 无效版本会被保留在结果中
    • 排序时将无效版本视为最小值
  • 用途: 对已创建的版本对象集合进行排序

排序算法特点:

  • 稳定排序:相等的版本保持原始顺序
  • 时间复杂度:O(n log n),其中n为版本数量
  • 空间复杂度:SortVersionStringSlice需要O(n)额外空间,SortVersionSlice为O(1)

注意事项:

  • 两个函数都不会修改原始输入切片,而是返回新的排序结果
  • 排序时会考虑版本的所有组成部分(前缀、数字、后缀)
  • 大多数情况下,排序结果符合语义化版本规范的预期顺序

示例:

// 排序版本号字符串
unsortedStrings := []string{
    "2.0.0", 
    "1.0.0", 
    "1.10.0", 
    "1.2.0",
    "v1.5.0",
    "1.5.0-beta",
}
sortedStrings := versions.SortVersionStringSlice(unsortedStrings)
fmt.Println("排序后的版本号字符串:")
for i, v := range sortedStrings {
    fmt.Printf("%d. %s\n", i+1, v)
}
// 输出:
// 排序后的版本号字符串:
// 1. 1.0.0
// 2. 1.2.0
// 3. 1.5.0-beta
// 4. v1.5.0
// 5. 1.10.0
// 6. 2.0.0

// 排序版本对象
unsortedVersions := []*versions.Version{
    versions.NewVersion("2.0.0"),
    versions.NewVersion("1.0.0"),
    versions.NewVersion("1.10.0"),
    versions.NewVersion("1.2.0-alpha"),
}
sortedVersions := versions.SortVersionSlice(unsortedVersions)
fmt.Println("排序后的版本对象:")
for i, v := range sortedVersions {
    fmt.Printf("%d. %s\n", i+1, v.Raw)
}
// 输出:
// 排序后的版本对象:
// 1. 1.0.0
// 2. 1.2.0-alpha
// 3. 1.10.0
// 4. 2.0.0

// 自定义排序:按发布时间倒序
// 注:需配合自定义排序函数使用
type ByReleaseTimeDesc []*versions.Version
func (v ByReleaseTimeDesc) Len() int           { return len(v) }
func (v ByReleaseTimeDesc) Swap(i, j int)      { v[i], v[j] = v[j], v[i] }
func (v ByReleaseTimeDesc) Less(i, j int) bool { return v[j].PublicTime.Before(v[i].PublicTime) }

// 设置发布时间并排序
for i, v := range unsortedVersions {
    // 模拟不同的发布时间,每个版本间隔1个月
    v.PublicTime = time.Now().AddDate(0, -i, 0)
}
sort.Sort(ByReleaseTimeDesc(unsortedVersions))
fmt.Println("按发布时间倒序排序:")
for i, v := range unsortedVersions {
    fmt.Printf("%d. %s (发布于: %s)\n", i+1, v.Raw, v.PublicTime.Format("2006-01-02"))
}
分组函数
版本分组函数
// 将版本列表按主版本号分组
func Group(versions []*Version) map[string]*VersionGroup

详细函数说明:

Group(versions []*Version): 将版本列表按主版本号分组

  • 参数: versions []*Version - 要分组的版本对象列表
  • 返回值: map[string]*VersionGroup - 以组ID为键的版本组映射
  • 行为:
    1. 遍历版本对象列表
    2. 对每个版本提取其主版本号(VersionNumbers[0])作为组ID
    3. 按组ID创建或更新 VersionGroup
    4. 将版本添加到对应的组中
  • 分组标准:
    • 默认按主版本号(第一个数字)分组
    • 无效版本或无主版本号的版本使用"0"作为组ID
  • 返回格式:
    • 键:字符串形式的组ID,通常是主版本号(如"1", "2")
    • 值:包含对应主版本号所有版本的 VersionGroup 对象
  • 用途:
    • 按主版本号组织版本
    • 创建层次化版本选择界面
    • 辅助版本号可视化

常见分组用例:

  • 按语义化版本的主版本号分组,快速区分不兼容版本
  • UI中显示分级版本选择器,方便用户选择合适版本
  • 对大量版本进行结构化管理,提高版本浏览和选择效率

性能特点:

  • 时间复杂度:O(n),其中n为版本数量
  • 空间复杂度:O(n),需要存储所有版本的组织结构
  • 适合处理任意规模的版本集合,性能随版本数量线性增长

示例:

// 创建版本列表
versionList := []*versions.Version{
    versions.NewVersion("1.0.0"),
    versions.NewVersion("1.1.0"),
    versions.NewVersion("1.2.0"),
    versions.NewVersion("2.0.0"),
    versions.NewVersion("2.1.0"),
    versions.NewVersion("3.0.0-beta"),
}

// 按主版本号分组
groupMap := versions.Group(versionList)

// 打印分组结果
fmt.Printf("共有 %d 个版本组\n", len(groupMap))
// 输出: 共有 3 个版本组

// 遍历分组结果
for groupID, group := range groupMap {
    fmt.Printf("\n版本组 %s 包含 %d 个版本:\n", groupID, group.Count())
    // 对组内版本排序
    sortedVersions := group.SortVersions()
    for i, v := range sortedVersions {
        fmt.Printf("  %d. %s\n", i+1, v.Raw)
    }
}
// 输出:
// 版本组 1 包含 3 个版本:
//   1. 1.0.0
//   2. 1.1.0
//   3. 1.2.0
//
// 版本组 2 包含 2 个版本:
//   1. 2.0.0
//   2. 2.1.0
//
// 版本组 3 包含 1 个版本:
//   1. 3.0.0-beta

// 获取特定组内的最新版本
group1 := groupMap["1"]
if group1 != nil && group1.Count() > 0 {
    sortedGroup1 := group1.SortVersions()
    latestVersion := sortedGroup1[len(sortedGroup1)-1]
    fmt.Printf("\n版本组 1 中的最新版本: %s\n", latestVersion.Raw)
    // 输出: 版本组 1 中的最新版本: 1.2.0
}

// 高级应用:创建版本选择器数据
type VersionOption struct {
    Label    string
    Value    string
    Children []VersionOption
}

versionSelector := make([]VersionOption, 0, len(groupMap))
for groupID, group := range groupMap {
    children := make([]VersionOption, 0, group.Count())
    for _, v := range group.SortVersions() {
        children = append(children, VersionOption{
            Label: v.Raw,
            Value: v.Raw,
        })
    }
    versionSelector = append(versionSelector, VersionOption{
        Label:    fmt.Sprintf("版本 %s.x", groupID),
        Value:    groupID,
        Children: children,
    })
}
可视化函数
版本可视化函数
// 以文本树形式可视化版本结构
func VisualizeVersions(versions []*Version, w io.Writer, maxItemsPerGroup int)

// 以文本树形式可视化版本组层次结构
func VisualizeVersionGroups(versions []*Version, w io.Writer)

详细函数说明:

VisualizeVersions(versions []*Version, w io.Writer, maxItemsPerGroup int): 以文本树形式可视化版本结构

  • 参数:
    • versions []*Version - 要可视化的版本对象列表
    • w io.Writer - 输出写入目标
    • maxItemsPerGroup int - 每组最多显示的版本数量,0表示不限制
  • 行为:
    1. 按主版本号对版本进行分组
    2. 为每个版本组创建树形结构
    3. 对组内版本排序并输出有限数量
    4. 如超过限制,显示剩余版本数
  • 输出格式:
    • 显示总版本数和版本组数
    • 每个版本组以树形结构展示
    • 可选显示版本的发布时间
  • 用途:
    • 在终端或日志中展示版本组织结构
    • 提供版本分布的直观视图
    • 方便调试和检查版本管理逻辑

VisualizeVersionGroups(versions []*Version, w io.Writer): 以文本树形式可视化版本组层次结构

  • 参数:
    • versions []*Version - 要可视化的版本对象列表
    • w io.Writer - 输出写入目标
  • 行为:
    1. 创建版本组层次结构
    2. 以树形结构输出版本组信息
    3. 对每个组显示组ID和版本数量
  • 输出格式:
    • 不显示具体版本,只展示组级别信息
    • 每组显示ID和包含的版本数量
  • 用途:
    • 获取版本分组的概览
    • 查看不同主版本的分布情况
    • 为大型版本集合提供简化视图

视觉效果增强:

  • 使用Unicode字符创建树形结构(如 "├──", "└──")
  • 缩进和连接线提高可读性
  • 可选颜色高亮(输出到终端时)

应用场景:

  • 版本库管理和维护
  • 发布日志和版本跟踪
  • 在CLI工具中展示版本信息
  • 调试版本比较和排序逻辑

示例:

// 准备版本列表
versionList := []*versions.Version{
    versions.NewVersion("1.0.0"),
    versions.NewVersion("1.0.1"),
    versions.NewVersion("1.1.0"),
    versions.NewVersion("2.0.0"),
    versions.NewVersion("2.0.1"),
    versions.NewVersion("2.1.0"),
    versions.NewVersion("3.0.0-alpha"),
    versions.NewVersion("3.0.0-beta"),
}

// 设置发布时间(示例)
currentTime := time.Now()
for i, v := range versionList {
    // 模拟不同发布时间,每个版本间隔1个月
    v.PublicTime = currentTime.AddDate(0, -i, 0)
}

// 可视化完整版本结构,每组显示最多2个版本
fmt.Println("完整版本可视化 (每组最多2个版本):")
versions.VisualizeVersions(versionList, os.Stdout, 2)
// 输出示例:
// 版本总数: 8
// 版本组数: 3
//
// ┌─ 版本组: 1 (3个版本)
// ├── 1.0.0 (发布时间: 2023-05-15)
// ├── 1.0.1 (发布时间: 2023-04-15)
// └── ...还有1个版本未显示
//
// ┌─ 版本组: 2 (3个版本)
// ├── 2.0.0 (发布时间: 2023-02-15)
// ├── 2.0.1 (发布时间: 2023-01-15)
// └── ...还有1个版本未显示
//
// ┌─ 版本组: 3 (2个版本)
// ├── 3.0.0-alpha (发布时间: 2022-12-15)
// └── 3.0.0-beta (发布时间: 2022-11-15)

// 仅可视化版本组结构
fmt.Println("\n版本组结构可视化:")
versions.VisualizeVersionGroups(versionList, os.Stdout)
// 输出示例:
// 版本总数: 8
// 版本组数: 3
//
// ┌─ 版本组: 1 (3个版本)
// ├─ 版本组: 2 (3个版本)
// └─ 版本组: 3 (2个版本)

// 可视化特定版本范围
fmt.Println("\n筛选后的版本可视化:")
// 获取1.x和2.x系列的所有版本
filteredVersions := make([]*versions.Version, 0)
for _, v := range versionList {
    major := v.VersionNumbers.MajorVersion()
    if major == 1 || major == 2 {
        filteredVersions = append(filteredVersions, v)
    }
}
versions.VisualizeVersions(filteredVersions, os.Stdout, 0) // 0表示显示所有版本

🔍 使用示例

示例 描述
📚 基本版本解析 如何解析和比较不同格式的版本号
📂 从文件读取版本 如何从文件中读取版本信息
🔢 版本排序 如何对版本号进行排序
📦 版本分组 如何对版本进行分组管理
🔍 版本范围查询 如何查询特定版本范围
📊 版本可视化 如何可视化版本结构
版本树示例
版本树可视化示例

⚠️ 注意事项

  • ⚠️ 确保传入的文件路径正确,且文件格式符合要求
  • ⚠️ 版本号的解析和比较依赖于正确的格式,非标准格式可能会导致解析错误
  • ⚠️ 时间比较依赖于 PublicTime 被正确设置
  • ⚠️ 对于非标准格式的版本号可能需要额外的处理

📈 性能

  • 版本解析: O(n),其中 n 是版本号字符串的长度
  • 版本比较: O(m),其中 m 是版本号中数字部分的最大长度
  • 版本排序: O(n log n),其中 n 是版本列表的长度
  • 范围查询: O(log n),基于有序版本组的二分查找

📄 许可证

本项目采用 MIT 许可证 - 详见 LICENSE 文件

Copyright © 2023-2025 scagogogo

Documentation

Index

Constants

View Source
const (
	// DefaultVersionDelimiter 默认的版本数字分隔符
	//
	// 这是用于连接版本号数字部分的标准分隔符。即使原始版本使用了其它分隔符(如"/"),
	// 解析完毕后也会被统一为这个标准分隔符(即".")。
	DefaultVersionDelimiter = "."
)

Variables

View Source
var (
	// ErrVersionInvalid 表示版本号格式无效的错误
	//
	// 当尝试解析不符合要求的版本号字符串时返回此错误
	ErrVersionInvalid = errors.New("version invalid")
)

Functions

func Group

func Group(versions []*Version) map[string]*VersionGroup

Group 对版本号进行分组

该函数将版本对象数组按照其数字部分(主版本号)进行分组,为每个不同的主版本号创建一个版本组。 分组的依据是版本号的数字部分生成的组ID,如 "1.2.3" 和 "1.2.4" 会被分到同一组 "1.2"。

分组可用于: 1. 对特定主版本系列进行管理和查询 2. 分析版本演进路径 3. 查找某主版本下的最新/最旧版本

参数:

  • versions: 需要分组的版本对象数组

返回:

  • map[string]*VersionGroup: 分组结果,键为版本组ID,值为对应的版本组对象

使用示例:

allVersions := versions.NewVersions("1.0.0", "1.1.0", "1.2.0", "2.0.0", "2.1.0")
groups := versions.Group(allVersions)

// 遍历所有版本组
for groupID, group := range groups {
    fmt.Printf("版本组 %s 包含 %d 个版本\n", groupID, len(group.Versions))

    // 获取组内最新版本
    latestVersion := group.GetLatestVersion()
    fmt.Printf("组内最新版本: %s\n", latestVersion.Raw)
}

func ReadVersionsStringFromFile

func ReadVersionsStringFromFile(filepath string) ([]string, error)

ReadVersionsStringFromFile 从文件中读取版本号字符串

该函数从指定的文件中读取版本号列表,每行一个版本号,并返回字符串数组。 与 ReadVersionsFromFile 不同,此函数不会将版本号解析为Version对象, 而是保留原始字符串形式,适用于不需要解析和比较的场景。

参数:

  • filepath: 包含版本号列表的文件路径

返回:

  • []string: 读取的版本号字符串数组
  • error: 如果文件读取失败则返回相应错误

使用示例:

// 从版本列表文件中读取版本字符串
versionStrings, err := versions.ReadVersionsStringFromFile("./versions.txt")
if err != nil {
    log.Fatalf("读取版本文件失败: %v", err)
}

// 使用版本字符串
for _, vStr := range versionStrings {
    fmt.Printf("发现版本: %s\n", vStr)
}

func SortVersionGroupSlice

func SortVersionGroupSlice(groupSlice []*VersionGroup)

SortVersionGroupSlice 对版本组切片进行排序

该函数直接对传入的版本组切片进行原地排序,排序依据是版本组之间的比较规则。

参数:

  • groupSlice: 待排序的版本组切片,排序操作直接修改该切片

使用示例:

groups := []*VersionGroup{group1, group2, group3}
SortVersionGroupSlice(groups)
// 现在 groups 已按版本组规则排序

func SortVersionStringSlice

func SortVersionStringSlice(versionStringSlice []string) []string

SortVersionStringSlice 对字符串形式的版本数组进行排序

该函数接收一个字符串形式的版本号数组,将其解析为 Version 对象进行排序, 然后将排序结果转换回字符串数组返回。排序遵循版本号的自然排序规则。

参数:

  • versionStringSlice: 待排序的版本号字符串数组

返回:

  • []string: 排序后的版本号字符串数组

使用示例:

versions := []string{"1.2.0", "1.0.0", "1.10.0", "2.0.0"}
sorted := versions.SortVersionStringSlice(versions)
// 结果: ["1.0.0", "1.2.0", "1.10.0", "2.0.0"]

func VisualizeVersionGroups

func VisualizeVersionGroups(versions []*Version, w io.Writer)

VisualizeVersionGroups 可视化版本组之间的关系

此函数将版本组集合转换为可视化的树状文本表示,展示其层次关系。 适合用于查看大型版本库的版本组织结构。

参数:

  • versions: 要可视化的版本集合
  • w: 输出写入的目标

示例:

versions := ReadVersionsFromFile("versions.txt")
VisualizeVersionGroups(versions, os.Stdout)

func VisualizeVersions

func VisualizeVersions(versions []*Version, w io.Writer, maxItems int)

VisualizeVersions 可视化版本号之间的关系和结构

此函数将版本号集合转换为可视化的文本表示,展示其层次关系和排序情况。 主要用于调试、展示或理解版本数据结构。

参数:

  • versions: 要可视化的版本集合
  • w: 输出写入的目标
  • maxItems: 每个版本组最多显示的版本数量,0表示不限制

示例:

versions := ReadVersionsFromFile("versions.txt")
VisualizeVersions(versions, os.Stdout, 5)

Types

type ContainsPolicy

type ContainsPolicy int

ContainsPolicy 用于控制版本查询时的包含/排除策略

该类型定义了在版本过滤或查询操作中,是否应包含或排除特定版本的策略选项。 它作为枚举类型使用,提供了三种可能的状态:未指定、包含和排除。

使用示例:

// 使用包含策略进行版本过滤
filter := &VersionFilter{
    Contains: "beta",
    ContainsPolicy: ContainsPolicyYes,
}

// 使用排除策略进行版本过滤
filter := &VersionFilter{
    Contains: "snapshot",
    ContainsPolicy: ContainsPolicyNo,
}
const (
	// ContainsPolicyNone 表示未指定包含策略
	//
	// 当设置为此值时,版本查询不会基于包含条件进行过滤
	ContainsPolicyNone ContainsPolicy = iota

	// ContainsPolicyYes 表示包含匹配的版本
	//
	// 当设置为此值时,只有包含指定字符串的版本才会被包含在结果中
	ContainsPolicyYes

	// ContainsPolicyNo 表示排除匹配的版本
	//
	// 当设置为此值时,包含指定字符串的版本将被排除在结果之外
	ContainsPolicyNo
)

type SortedVersionGroups

type SortedVersionGroups struct {
	// contains filtered or unexported fields
}

SortedVersionGroups 表示已排序的版本组集合

SortedVersionGroups 封装了已排序的版本组切片和索引映射, 用于高效地进行版本组查询和范围检索。它通过预先排序和建立索引, 优化了版本组的查找性能。

结构特点: 1. 保持版本组的有序性,便于范围查询 2. 维护组ID到数组索引的映射,支持快速定位 3. 支持基于版本范围的高效查询

使用示例:

// 创建已排序的版本组
allVersions := versions.NewVersions("1.0.0", "1.1.0", "2.0.0", "2.1.0")
sortedGroups := versions.NewSortedVersionGroups(allVersions)

// 执行范围查询
startVer := versions.NewVersion("1.0.0")
endVer := versions.NewVersion("2.0.0")
startTuple := tuple.NewTuple2(startVer, versions.ContainsPolicyYes)
endTuple := tuple.NewTuple2(endVer, versions.ContainsPolicyYes)

rangeResult := sortedGroups.QueryRange(startTuple, endTuple)

func NewSortedVersionGroups

func NewSortedVersionGroups(versions []*Version) *SortedVersionGroups

NewSortedVersionGroups 为版本号创建有序的分组

该方法接收一个版本对象数组,将其分组并排序,返回一个包含已排序版本组的SortedVersionGroups对象。 处理流程: 1. 首先将版本按照其数字部分分组 2. 然后对所有分组进行排序 3. 最后构建组ID到索引的映射,用于快速查找

参数:

  • versions: 需要分组和排序的版本对象数组

返回:

  • *SortedVersionGroups: 包含已排序版本组的对象

使用示例:

// 创建版本对象数组
allVersions := versions.NewVersions("1.0.0", "1.1.0", "1.2.0", "2.0.0", "2.1.0")

// 创建已排序的版本组
sortedGroups := versions.NewSortedVersionGroups(allVersions)

func (*SortedVersionGroups) GroupIDs

func (x *SortedVersionGroups) GroupIDs() []string

GroupIDs 返回所有版本组的ID列表

该方法返回按顺序排列的版本组ID列表。 返回的ID列表与内部的版本组切片顺序一致,确保保持排序状态。

返回:

  • []string: 含有所有版本组ID的字符串切片

使用示例:

sortedGroups := versions.NewSortedVersionGroups(allVersions)
groupIDs := sortedGroups.GroupIDs()
for _, id := range groupIDs {
    fmt.Printf("版本组: %s\n", id)
}

func (*SortedVersionGroups) QueryRange

func (x *SortedVersionGroups) QueryRange(start, end *tuple.Tuple2[*Version, ContainsPolicy]) []*Version

QueryRange 在有序版本组中查询指定范围内的版本

该方法根据给定的起始和结束版本范围,返回所有符合条件的版本对象数组。 方法利用预排序的版本组结构,快速定位并收集符合范围条件的版本。

参数:

  • start: 包含起始版本和包含策略的元组
  • end: 包含结束版本和包含策略的元组

返回:

  • []*Version: 符合查询范围条件的版本对象数组

使用示例:

// 创建已排序的版本组
sortedGroups := versions.NewSortedVersionGroups(allVersions)

// 定义查询范围
startVer := versions.NewVersion("1.0.0")
endVer := versions.NewVersion("2.0.0")
startTuple := tuple.NewTuple2(startVer, versions.ContainsPolicyYes) // 包含1.0.0
endTuple := tuple.NewTuple2(endVer, versions.ContainsPolicyNo)      // 不包含2.0.0

// 执行范围查询
rangeResult := sortedGroups.QueryRange(startTuple, endTuple)
fmt.Printf("在范围内的版本数: %d\n", len(rangeResult))

type Version

type Version struct {

	// Raw 原始的版本号字符串
	Raw string `json:"raw"`

	// PublicTime 此版本的发布时间
	PublicTime time.Time `json:"public_time"`

	// VersionNumbers 版本号中的数字部分
	// 例如对于版本号 "v1.2.3-beta1",VersionNumbers 为 [1,2,3]
	VersionNumbers VersionNumbers `json:"version_numbers"`

	// Prefix 版本号数字部分之前的前缀
	// 例如对于版本号 "v1.2.3",Prefix 为 "v"
	Prefix VersionPrefix `json:"prefix"`

	// Suffix 版本号数字部分之后的后缀
	// 例如对于版本号 "1.2.3-beta1",Suffix 为 "-beta1"
	Suffix VersionSuffix `json:"suffix"`
}

Version 用于表示一个版本号

Version 结构体封装了版本号的各个组成部分,包括原始字符串、发布时间、数字部分、 前缀和后缀。它支持版本号的解析、比较和分组等操作,实现了 Comparable 接口以便 进行版本排序。

一个典型的版本号格式可能为:v1.2.3-beta1,其中: - "v" 是前缀 - "1.2.3" 是数字部分 - "-beta1" 是后缀

使用示例:

// 创建一个版本对象
version := versions.NewVersion("v1.2.3-rc1")

// 检查版本是否有效
if version.IsValid() {
    fmt.Printf("版本号有效: %s\n", version.Raw)
    fmt.Printf("版本号数字部分: %v\n", version.VersionNumbers)
}

// 比较两个版本
v1 := versions.NewVersion("1.2.3")
v2 := versions.NewVersion("1.3.0")
if v1.CompareTo(v2) < 0 {
    fmt.Println("v1 比 v2 旧")
}

func NewVersion

func NewVersion(versionStr string) *Version

NewVersion 从版本字符串创建一个新的 Version 对象

该方法解析给定的版本字符串,并返回一个填充了相应字段的 Version 对象。 即使版本字符串格式不正确,该方法也会返回一个对象,但其 IsValid() 方法可能返回 false。

参数:

  • versionStr: 要解析的版本号字符串,如 "1.2.3" 或 "v1.2.3-rc1"

返回:

  • *Version: 解析后的 Version 对象

使用示例:

version := versions.NewVersion("v1.2.3-beta1")

func NewVersionE

func NewVersionE(versionStr string) (*Version, error)

NewVersionE 从版本字符串创建一个新的 Version 对象,并返回可能的错误

与 NewVersion 不同,该方法会在版本字符串格式不正确时返回错误。

参数:

  • versionStr: 要解析的版本号字符串

返回:

  • *Version: 解析后的 Version 对象,如果解析失败则为 nil
  • error: 如果版本号无效,则返回 ErrVersionInvalid 错误

使用示例:

version, err := versions.NewVersionE("v1.2.3-beta1")
if err != nil {
    log.Fatalf("无效的版本号: %v", err)
}

func NewVersions

func NewVersions(versionStringSlice ...string) []*Version

NewVersions 批量创建多个 Version 对象

该方法接受多个版本字符串,并返回相应的 Version 对象数组。

参数:

  • versionStringSlice: 一个或多个版本号字符串

返回:

  • []*Version: 解析后的 Version 对象数组

使用示例:

versions := versions.NewVersions("1.0.0", "1.1.0", "2.0.0")
for _, v := range versions {
    fmt.Println(v.Raw)
}

func ReadVersionsFromFile

func ReadVersionsFromFile(filepath string) ([]*Version, error)

ReadVersionsFromFile 从文件中读取版本号并解析为Version对象

该函数从指定的文件中读取版本号列表,每行一个版本号,并将其解析为Version对象数组。 函数会自动忽略空行和进行行尾空白字符的清理。

参数:

  • filepath: 包含版本号列表的文件路径

返回:

  • []*Version: 解析后的Version对象数组
  • error: 如果文件读取失败则返回相应错误

示例文件内容:

1.1.28
1.1.29
1.1.30
1.1.31
1.1.31.sec01
1.1.31.sec04
1.1.31.sec06

使用示例:

// 从版本列表文件中读取版本
versions, err := versions.ReadVersionsFromFile("./versions.txt")
if err != nil {
    log.Fatalf("读取版本文件失败: %v", err)
}

// 打印解析的版本数
fmt.Printf("共读取 %d 个版本\n", len(versions))

// 对版本进行排序
sortedVersions := versions.SortVersionSlice(versions)

func SortVersionSlice

func SortVersionSlice(versions []*Version) []*Version

SortVersionSlice 对版本号对象数组进行排序

该函数实现了版本号的分组排序算法: 1. 首先将版本号按照主版本号分组 2. 对版本组进行排序 3. 在每个组内对版本号进行排序 4. 最后将所有组中的版本号按顺序合并

参数:

  • versions: 待排序的版本号对象数组

返回:

  • []*Version: 排序后的版本号对象数组

使用示例:

versions := versions.NewVersions("1.2.0", "1.0.0", "1.10.0", "2.0.0")
sorted := versions.SortVersionSlice(versions)
for _, v := range sorted {
    fmt.Println(v.Raw)
}

func (*Version) BuildGroupID

func (x *Version) BuildGroupID() string

BuildGroupID 构造版本所属的组的ID

该方法根据版本号的数字部分生成一个组ID,用于将相似版本分组。

返回:

  • string: 表示版本组的ID字符串

使用示例:

version := versions.NewVersion("1.2.3")
groupID := version.BuildGroupID()
fmt.Printf("版本组ID: %s\n", groupID)

func (*Version) CompareTo

func (x *Version) CompareTo(target *Version) int

CompareTo 比较两个版本号

该方法按以下顺序比较两个版本号: 1. 首先比较主版本号数字部分 2. 其次比较发布时间 3. 然后比较后缀 4. 最后比较原始版本号字符串

参数:

  • target: 要比较的目标版本对象

返回:

  • int: 如果当前版本小于目标版本,返回-1;如果相等,返回0;如果大于,返回1

使用示例:

v1 := versions.NewVersion("1.0.0")
v2 := versions.NewVersion("1.1.0")

switch v1.CompareTo(v2) {
case -1:
    fmt.Println("v1 < v2")
case 0:
    fmt.Println("v1 = v2")
case 1:
    fmt.Println("v1 > v2")
}

func (*Version) IsValid

func (v *Version) IsValid() bool

IsValid 检查版本号是否有效

判断依据是版本号中是否包含数字部分。只有当解析到了版本号数字时才认为是有效的版本号。

返回:

  • bool: 如果版本号有效则返回 true,否则返回 false

使用示例:

version := versions.NewVersion("not-a-version")
if !version.IsValid() {
    fmt.Println("无效的版本号")
}

func (*Version) String

func (x *Version) String() string

String 返回版本的JSON字符串表示

该方法将Version对象序列化为JSON字符串,便于打印和调试。

返回:

  • string: 版本的JSON字符串表示

使用示例:

version := versions.NewVersion("1.2.3")
fmt.Println(version.String()) // 输出JSON格式的版本信息

type VersionGroup

type VersionGroup struct {

	// GroupVersionNumbers 组的版本号中的数字部分
	// 例如对于版本号 "1.2.x",GroupVersionNumbers 为 [1,2]
	GroupVersionNumbers VersionNumbers

	// VersionMap 组中包含的所有版本,键为版本的原始字符串,值为版本对象
	VersionMap map[string]*Version
}

VersionGroup 表示一个版本组,一个版本组中可能有一个或多个版本

VersionGroup 用于管理具有相同主版本号数字部分的一组版本。它提供了版本的添加、查询、排序和范围查询等功能。 版本组是版本管理系统中的重要概念,用于将相似版本聚合在一起,便于进行版本管理和分析。

每个版本组都有一个唯一的ID,由其主版本号数字部分生成,如 "1.2"。

使用示例:

// 创建一个新的版本组
group := versions.NewVersionGroup(versions.NewVersionNumbers([]int{1, 2}))

// 添加版本到组中
v1 := versions.NewVersion("1.2.0")
v2 := versions.NewVersion("1.2.1")
group.Add(v1)
group.Add(v2)

// 获取组中的所有版本
allVersions := group.Versions()

// 获取排序后的版本
sortedVersions := group.SortVersions()

func NewVersionGroup

func NewVersionGroup(groupVersionNumbers VersionNumbers) *VersionGroup

NewVersionGroup 创建一个新的版本组

该方法根据指定的版本号数字部分创建一个新的版本组。创建时需要传递能够在包范围下唯一区分组的组ID, 这个ID选择的是版本中的数字部分。

参数:

  • groupVersionNumbers: 版本组的数字部分,如 [1,2] 表示 "1.2" 版本组

返回:

  • *VersionGroup: 新创建的版本组对象

使用示例:

// 创建表示 "1.2" 版本组的对象
group := versions.NewVersionGroup(versions.NewVersionNumbers([]int{1, 2}))

func NewVersionGroupFromVersions

func NewVersionGroupFromVersions(versions []*Version) *VersionGroup

NewVersionGroupFromVersions 从版本数组创建一个版本组

该方法基于给定的版本数组创建一个版本组。所有版本将被添加到同一个组中, 该组的数字部分取自第一个版本的数字部分。

参数:

  • versions: 要添加到组中的版本数组

返回:

  • *VersionGroup: 新创建的包含所有指定版本的版本组,如果输入为空则返回 nil

使用示例:

versions := versions.NewVersions("1.2.0", "1.2.1", "1.2.2")
group := versions.NewVersionGroupFromVersions(versions)

func SortVersionGroupMap

func SortVersionGroupMap(versionGroupMap map[string]*VersionGroup) []*VersionGroup

SortVersionGroupMap 对版本组映射进行排序

该函数将版本组映射转换为切片,并对切片中的版本组进行排序。

参数:

  • versionGroupMap: 版本组映射,键为版本组ID,值为版本组对象

返回:

  • []*VersionGroup: 排序后的版本组切片

使用示例:

groupMap := Group(versions)
sortedGroups := SortVersionGroupMap(groupMap)
for _, group := range sortedGroups {
    fmt.Printf("组: %s, 版本数: %d\n", group.GroupID, len(group.Versions))
}

func (*VersionGroup) Add

func (x *VersionGroup) Add(v *Version) bool

Add 把给定的版本添加到本版本组中

该方法将指定的版本添加到版本组中。如果版本已存在,则会被覆盖。

参数:

  • v: 要添加的版本对象

返回:

  • bool: 如果版本之前已存在于组中则返回 true,否则返回 false

使用示例:

group := versions.NewVersionGroup(versions.NewVersionNumbers([]int{1, 2}))
version := versions.NewVersion("1.2.3")
exists := group.Add(version)
if !exists {
    fmt.Println("添加了新版本")
}

func (*VersionGroup) CompareTo

func (x *VersionGroup) CompareTo(target *VersionGroup) int

CompareTo 比较两个版本组的大小

该方法通过比较版本组的数字部分来确定两个版本组的先后顺序。

参数:

  • target: 要比较的目标版本组

返回:

  • int: 如果当前版本组小于目标版本组,返回负数;如果相等,返回0;如果大于,返回正数

使用示例:

group1 := versions.NewVersionGroup(versions.NewVersionNumbers([]int{1, 2}))
group2 := versions.NewVersionGroup(versions.NewVersionNumbers([]int{1, 3}))

if group1.CompareTo(group2) < 0 {
    fmt.Println("group1 比 group2 旧")
}

func (*VersionGroup) Contains

func (x *VersionGroup) Contains(v *Version) bool

Contains 判断本版本组中是否包含给定的版本

该方法检查指定的版本是否已存在于版本组中。

参数:

  • v: 要检查的版本对象

返回:

  • bool: 如果版本存在于组中则返回 true,否则返回 false

使用示例:

group := versions.NewVersionGroup(versions.NewVersionNumbers([]int{1, 2}))
version := versions.NewVersion("1.2.3")
if !group.Contains(version) {
    group.Add(version)
}

func (*VersionGroup) ID

func (x *VersionGroup) ID() string

ID 返回组的ID

该方法返回版本组的唯一标识符,由其数字部分生成。

返回:

  • string: 版本组的ID,例如 "1.2"

使用示例:

group := versions.NewVersionGroup(versions.NewVersionNumbers([]int{1, 2}))
groupID := group.ID() // 返回 "1.2"

func (*VersionGroup) QueryRangeVersions

func (x *VersionGroup) QueryRangeVersions(start, end *tuple.Tuple2[*Version, ContainsPolicy]) []*Version

QueryRangeVersions 获取组内指定区间内的版本

该方法根据给定的起始和结束版本范围,返回组内符合条件的版本数组。 版本的包含性由 ContainsPolicy 参数控制。

参数:

  • start: 包含起始版本和包含策略的元组
  • end: 包含结束版本和包含策略的元组

返回:

  • []*Version: 符合区间条件的版本数组

使用示例:

group := versions.NewVersionGroupFromVersions(versions.NewVersions("1.2.0", "1.2.1", "1.2.2", "1.2.3"))

// 查询 1.2.0(包含)到 1.2.2(包含)的版本
startTuple := tuple.NewTuple2(versions.NewVersion("1.2.0"), versions.ContainsPolicyYes)
endTuple := tuple.NewTuple2(versions.NewVersion("1.2.2"), versions.ContainsPolicyYes)

rangeVersions := group.QueryRangeVersions(startTuple, endTuple)
// 结果包含: ["1.2.0", "1.2.1", "1.2.2"]

func (*VersionGroup) SortVersions

func (x *VersionGroup) SortVersions() []*Version

SortVersions 对组下的所有版本进行排序返回

该方法返回版本组中所有版本的有序数组,排序遵循版本号的自然排序规则。

返回:

  • []*Version: 排序后的版本数组

使用示例:

group := versions.NewVersionGroupFromVersions(versions.NewVersions("1.2.2", "1.2.0", "1.2.1"))
sortedVersions := group.SortVersions()
// 结果顺序: ["1.2.0", "1.2.1", "1.2.2"]

func (*VersionGroup) Versions

func (x *VersionGroup) Versions() []*Version

Versions 返回组下的所有版本

该方法返回版本组中包含的所有版本的数组,结果不保证有序。

返回:

  • []*Version: 版本组中所有版本的数组

使用示例:

group := versions.NewVersionGroupFromVersions(versions.NewVersions("1.2.0", "1.2.1"))
allVersions := group.Versions()
fmt.Printf("组中包含 %d 个版本\n", len(allVersions))

type VersionNumbers

type VersionNumbers []int

VersionNumbers 表示版本号中的数字部分

VersionNumbers 是一个整数切片类型,用于表示和操作版本号的数字部分。 例如对于版本号 "v1.2.3-beta1",其 VersionNumbers 为 [1,2,3]。 它实现了 Comparable 接口,支持版本号数字部分的比较操作。

使用示例:

// 创建一个版本号数字部分
numbers := versions.NewVersionNumbers([]int{1, 2, 3})

// 获取版本组ID
groupID := numbers.BuildGroupID() // 返回 "1.2.3"

// 比较两个版本号数字部分
other := versions.NewVersionNumbers([]int{1, 3, 0})
if numbers.CompareTo(other) < 0 {
    fmt.Println("1.2.3 比 1.3.0 旧")
}

func NewVersionNumbers

func NewVersionNumbers(versionNumbers []int) VersionNumbers

NewVersionNumbers 创建一个新的 VersionNumbers 对象

该方法将整数切片转换为 VersionNumbers 类型,便于进行版本号相关操作。

参数:

  • versionNumbers: 表示版本号的整数切片,如 [1,2,3] 表示版本号 "1.2.3"

返回:

  • VersionNumbers: 一个新的 VersionNumbers 对象

使用示例:

numbers := versions.NewVersionNumbers([]int{1, 2, 3})

func (VersionNumbers) BuildGroupID

func (x VersionNumbers) BuildGroupID() string

BuildGroupID 根据版本号数字部分构造版本组的ID

该方法将版本号数字部分以默认分隔符(".")连接成字符串,用于表示版本组ID。 版本组ID可用于对相同主版本号的版本进行分组和管理。

返回:

  • string: 版本组ID字符串,例如 "1.2.3"

使用示例:

numbers := versions.NewVersionNumbers([]int{1, 2, 3})
groupID := numbers.BuildGroupID() // 返回 "1.2.3"

// 可用于版本分组
versionGroups := make(map[string][]*Version)
for _, version := range allVersions {
    groupID := version.VersionNumbers.BuildGroupID()
    versionGroups[groupID] = append(versionGroups[groupID], version)
}

func (VersionNumbers) CompareTo

func (x VersionNumbers) CompareTo(target []int) int

CompareTo 比较两个版本号数字部分的大小

该方法按照版本号比较规则,从左到右逐位比较两个版本号数字部分的大小。 对于不同长度的版本号,首先比较共有部分,如果共有部分相等,则较长的版本号更大。

参数:

  • target: 要比较的目标版本号数字部分

返回:

  • int: 如果当前版本小于目标版本,返回负数;如果相等,返回0;如果大于,返回正数

使用示例:

v1 := versions.NewVersionNumbers([]int{1, 0, 0})
v2 := versions.NewVersionNumbers([]int{1, 1, 0})

result := v1.CompareTo(v2)
if result < 0 {
    fmt.Println("v1 比 v2 旧")
} else if result > 0 {
    fmt.Println("v1 比 v2 新")
} else {
    fmt.Println("v1 和 v2 相等")
}

type VersionPrefix

type VersionPrefix string

VersionPrefix 表示版本中数字部分之前的部分

VersionPrefix 是一个字符串类型,用于表示和操作版本号的前缀部分。 在版本号格式中,前缀是位于数字部分之前的字符串,如 "v1.2.3" 中的 "v"。 前缀可以为空,表示版本号直接以数字部分开始,如 "1.2.3"。

使用示例:

// 检查前缀是否为空
prefix := versions.VersionPrefix("v")
if !prefix.IsEmpty() {
    fmt.Printf("版本前缀: %s\n", prefix)
}

// 在解析版本号时处理前缀
version := versions.NewVersion("v1.2.3")
fmt.Printf("版本 %s 的前缀是: %s\n", version.Raw, version.Prefix)
const EmptyVersionPrefix VersionPrefix = ""

EmptyVersionPrefix 表示一个空的前缀

该常量用于表示版本号没有前缀的情况,如纯数字版本号 "1.2.3"。 它也用于检查版本前缀是否为空。

func (VersionPrefix) IsEmpty

func (x VersionPrefix) IsEmpty() bool

IsEmpty 返回前缀是否为空

该方法检查版本前缀是否为空,即是否等于 EmptyVersionPrefix。

返回:

  • bool: 如果前缀为空则返回 true,否则返回 false

使用示例:

version := versions.NewVersion("1.2.3") // 没有前缀
if version.Prefix.IsEmpty() {
    fmt.Println("版本没有前缀")
}

version2 := versions.NewVersion("v1.2.3") // 有前缀
if !version2.Prefix.IsEmpty() {
    fmt.Printf("版本前缀是: %s\n", version2.Prefix)
}

type VersionStringParser

type VersionStringParser struct {
	// contains filtered or unexported fields
}

VersionStringParser 把版本从字符串形式解析为struct

VersionStringParser 负责将版本号字符串解析为结构化的 Version 对象。 它实现了版本号字符串的词法分析,将字符串划分为前缀、数字部分和后缀三个组成部分。

解析过程: 1. 首先识别和提取版本号的前缀部分(如 "v") 2. 然后识别和提取版本号的数字部分(如 "1.2.3") 3. 最后识别和提取版本号的后缀部分(如 "-beta1")

使用示例:

// 创建一个版本解析器
parser := versions.NewVersionStringParser("v1.2.3-beta1")

// 解析版本字符串
version := parser.Parse()

// 使用解析结果
fmt.Printf("前缀: %s\n", version.Prefix)
fmt.Printf("数字部分: %v\n", version.VersionNumbers)
fmt.Printf("后缀: %s\n", version.Suffix)

func NewVersionStringParser

func NewVersionStringParser(versionStr string) *VersionStringParser

NewVersionStringParser 创建一个版本号Parser

该方法创建一个新的版本号解析器实例。每次解析都需要重新创建新的Parser, 因为解析状态保存在Parser对象中。

参数:

  • versionStr: 要解析的版本号字符串

返回:

  • *VersionStringParser: 新创建的版本号解析器

使用示例:

parser := versions.NewVersionStringParser("v1.2.3-rc1")
version := parser.Parse()

func (*VersionStringParser) IsDigit

func (x *VersionStringParser) IsDigit(c rune) bool

IsDigit 判断是否是数字

该方法检查给定的字符是否为数字字符(0-9)。

参数:

  • c: 要检查的字符

返回:

  • bool: 如果是数字则返回 true,否则返回 false

func (*VersionStringParser) IsVersionNumberDelimiter

func (x *VersionStringParser) IsVersionNumberDelimiter(c rune) bool

IsVersionNumberDelimiter 判断是否是版本数字的分隔符

该方法检查给定的字符是否为版本号数字部分的分隔符(目前仅支持点号)。

参数:

  • c: 要检查的字符

返回:

  • bool: 如果是分隔符则返回 true,否则返回 false

func (*VersionStringParser) Parse

func (x *VersionStringParser) Parse() *Version

Parse 解析版本号字符串

该方法按照预定义的规则解析版本号字符串,提取前缀、数字部分和后缀, 并构造一个完整的 Version 对象返回。

返回:

  • *Version: 解析后的版本对象

使用示例:

parser := versions.NewVersionStringParser("v1.2.3-beta1")
version := parser.Parse()
fmt.Printf("版本号: %s\n", version.Raw)

type VersionSuffix

type VersionSuffix string

VersionSuffix 表示版本号的后缀,版本号中数字后面的部分

VersionSuffix 是一个字符串类型,用于表示和操作版本号的后缀部分。 在版本号格式中,后缀是位于数字部分之后的字符串,如 "1.2.3-beta1" 中的 "-beta1"。 后缀通常用于表示预发布版本、构建元数据或其他版本标识信息。

后缀可以为空,表示版本号仅包含数字部分,如 "1.2.3"。

使用示例:

// 检查后缀是否为空
suffix := versions.VersionSuffix("-beta1")
if !suffix.IsEmpty() {
    fmt.Printf("版本后缀: %s\n", suffix)
}

// 比较后缀的优先级
suffix1 := versions.VersionSuffix("-alpha")
suffix2 := versions.VersionSuffix("-beta")
if suffix1.CompareTo(suffix2) < 0 {
    fmt.Println("alpha 后缀的优先级低于 beta 后缀")
}
const EmptyVersionSuffix VersionSuffix = ""

EmptyVersionSuffix 空的后缀

该常量用于表示版本号没有后缀的情况,如纯数字版本号 "1.2.3"。 它也用于检查版本后缀是否为空。

func (VersionSuffix) CompareTo

func (x VersionSuffix) CompareTo(target VersionSuffix) int

CompareTo 比较两个版本后缀的优先级

该方法根据字典序比较两个版本后缀的优先级。目前使用简单的字符串比较, 未来计划引入权重系统,为不同类型的后缀(如 alpha、beta、rc)分配不同的权重。

参数:

  • target: 要比较的目标版本后缀

返回:

  • int: 如果当前后缀优先级低于目标后缀,返回-1;如果相等,返回0;如果高于,返回1

使用示例:

suffix1 := versions.VersionSuffix("-alpha1")
suffix2 := versions.VersionSuffix("-beta1")

result := suffix1.CompareTo(suffix2)
if result < 0 {
    fmt.Println("alpha1 后缀的优先级低于 beta1 后缀")
}

注意:

  • TODO 2023-5-16 17:26:02 未来将引入后缀权重系统,使不同类型后缀的比较更符合语义化版本规范

func (VersionSuffix) IsEmpty

func (x VersionSuffix) IsEmpty() bool

IsEmpty 判断版本后缀是否为空

该方法检查版本后缀是否为空,即是否等于 EmptyVersionSuffix。

返回:

  • bool: 如果后缀为空则返回 true,否则返回 false

使用示例:

version := versions.NewVersion("1.2.3") // 没有后缀
if version.Suffix.IsEmpty() {
    fmt.Println("版本没有后缀")
}

version2 := versions.NewVersion("1.2.3-rc1") // 有后缀
if !version2.Suffix.IsEmpty() {
    fmt.Printf("版本后缀是: %s\n", version2.Suffix)
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL