Documentation
¶
Overview ¶
Package version provides semantic version parsing and comparison with flexible precision support.
Overview ¶
This package implements a subset of semantic versioning (semver.org) with a focus on precision-aware version comparison. It supports three precision levels:
- Major only (e.g., "1" or "v1")
- Major.Minor (e.g., "1.2" or "v1.2")
- Major.Minor.Patch (e.g., "1.2.3" or "v1.2.3")
The key feature is precision-aware comparison: a version with lower precision acts as a wildcard for missing components. For example:
- v1 matches v1.0.0, v1.5.0, v1.99.99 (any minor/patch)
- v1.2 matches v1.2.0, v1.2.1, v1.2.99 (any patch)
- v1.2.3 matches only v1.2.3 exactly
Usage ¶
Parse a version string:
v, err := version.ParseVersion("v1.2.3")
if err != nil {
// Handle error
}
fmt.Println(v.String()) // Output: 1.2.3
Compare versions:
current, _ := version.ParseVersion("v1.2")
required, _ := version.ParseVersion("1.2.5")
if current.EqualsOrNewer(required) {
fmt.Println("Version requirement met")
}
Create versions programmatically:
v := version.NewVersion(1, 2, 3) fmt.Println(v.String()) // Output: 1.2.3
Precision Semantics ¶
The Precision field determines how many components are significant:
- Precision 1: Only Major is significant (Minor/Patch ignored in comparisons)
- Precision 2: Major and Minor are significant (Patch ignored)
- Precision 3: All components are significant
When comparing versions, the comparison uses the lower precision of the two versions. This allows a version like "1.2" to match "1.2.0", "1.2.1", etc.
Semantic Versioning Compatibility ¶
This package implements a subset of semantic versioning:
Supported:
- Major.Minor.Patch version components
- Optional "v" prefix
- Flexible precision (1-3 components)
- Numeric version components
Not Supported (may be added in future):
- Prerelease identifiers (e.g., "1.2.3-alpha")
- Build metadata (e.g., "1.2.3+build.123")
- Version ranges or constraints
Error Handling ¶
The ParseVersion function returns specific errors for different failure modes:
- ErrEmptyVersion: Input string is empty
- ErrTooManyComponents: More than 3 version components
- ErrNonNumeric: Component contains non-numeric characters
- ErrNegativeComponent: Component is a negative number
For constant initialization, use MustParseVersion which panics on error:
var MinVersion = version.MustParseVersion("1.0.0")
Example (Precision) ¶
Example_precision demonstrates how precision affects version matching
// v1 has precision 1 (Major only)
major, _ := ParseVersion("v1")
// These all match because major is the only significant component
fmt.Println(major.EqualsOrNewer(Version{Major: 1, Minor: 0, Patch: 0, Precision: 3}))
fmt.Println(major.EqualsOrNewer(Version{Major: 1, Minor: 5, Patch: 0, Precision: 3}))
fmt.Println(major.EqualsOrNewer(Version{Major: 1, Minor: 99, Patch: 99, Precision: 3}))
// This doesn't match because major differs
fmt.Println(major.EqualsOrNewer(Version{Major: 2, Minor: 0, Patch: 0, Precision: 3}))
Output: true true true false
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrEmptyVersion = errors.New("version string is empty") ErrTooManyComponents = errors.New("version has more than 3 components") ErrNonNumeric = errors.New("version component is not numeric") ErrNegativeComponent = errors.New("version component cannot be negative") )
Error types for version parsing failures
Functions ¶
This section is empty.
Types ¶
type Version ¶
type Version struct {
Major int `json:"major,omitempty" yaml:"major,omitempty"`
Minor int `json:"minor,omitempty" yaml:"minor,omitempty"`
Patch int `json:"patch,omitempty" yaml:"patch,omitempty"`
// Precision indicates how many components are significant (1, 2, or 3)
Precision int `json:"precision,omitempty" yaml:"precision,omitempty"`
// Extras stores additional version metadata like "-1028-aws" or "-eks-3025e55"
Extras string `json:"extras,omitempty" yaml:"extras,omitempty"`
}
Version represents a semantic version number with Major, Minor, and Patch components. It supports flexible precision (1, 2, or 3 components) and preserves additional version metadata such as build suffixes (e.g., "-eks-3025e55", "-gke.1337000"). The Precision field indicates how many components are significant for comparisons.
func MustParseVersion ¶
MustParseVersion parses a version string and panics if parsing fails. This function is useful for initializing package-level constants or test data where the version string is known to be valid at compile time.
Only use this for hardcoded strings or in tests. For user input or runtime data, always use ParseVersion and handle errors explicitly.
Example usage:
v := version.MustParseVersion("1.33.0") // OK in init() or tests
v, err := version.ParseVersion(userInput) // Required for runtime data
func NewVersion ¶
NewVersion creates a new Version with the specified major, minor, and patch values. The precision is automatically set to 3 (all components are significant). Use ParseVersion for parsing version strings or creating versions with different precision.
Example ¶
ExampleNewVersion demonstrates creating a version programmatically
v := NewVersion(1, 2, 3)
fmt.Println(v.String())
fmt.Printf("Major: %d, Minor: %d, Patch: %d, Precision: %d\n", v.Major, v.Minor, v.Patch, v.Precision)
Output: 1.2.3 Major: 1, Minor: 2, Patch: 3, Precision: 3
func ParseVersion ¶
ParseVersion parses a version string into a Version struct. Supported formats: "1", "1.2", "1.2.3", "v1.2.3", "1.2.3-suffix", "1.2.3+metadata". The "v" prefix is optional and stripped if present. Additional metadata after '-' or '+' is preserved in the Extras field. Returns an error if the version string is empty, has invalid components, or has too many components.
Example ¶
ExampleParseVersion demonstrates how to parse version strings
// Parse various version formats
v1, _ := ParseVersion("1")
v2, _ := ParseVersion("v1.2")
v3, _ := ParseVersion("1.2.3")
fmt.Println(v1.String())
fmt.Println(v2.String())
fmt.Println(v3.String())
Output: 1 1.2 1.2.3
func (Version) Compare ¶
Compare returns an integer comparing two versions: -1 if v < other, 0 if v == other, 1 if v > other. This comparison respects precision like EqualsOrNewer. Useful for sorting versions.
Example ¶
ExampleVersion_Compare demonstrates sorting versions
v1, _ := ParseVersion("1.2.0")
v2, _ := ParseVersion("1.2.3")
v3, _ := ParseVersion("1.3.0")
fmt.Println(v1.Compare(v2)) // v1 < v2
//nolint:gocritic // intentional self-comparison for demonstration
fmt.Println(v2.Compare(v2)) // v2 == v2
fmt.Println(v3.Compare(v1)) // v3 > v1
Output: -1 0 1
func (Version) Equals ¶
Equals returns true if v exactly equals other (all components match). Unlike EqualsOrNewer, this ignores precision and compares all fields.
func (Version) EqualsOrNewer ¶
EqualsOrNewer returns true if v is equal to or newer than other. Comparison is performed up to the precision of v. For example, Version{Major:1, Minor:2, Precision:2} matches any 1.2.x version.
Example ¶
ExampleVersion_EqualsOrNewer demonstrates precision-aware version comparison
// Parse versions with different precisions
v1, _ := ParseVersion("v1.2") // Precision 2: Major.Minor
v2, _ := ParseVersion("1.2.5") // Precision 3: Full version
v3, _ := ParseVersion("1.3.0") // Precision 3: Full version
// v1.2 matches v1.2.5 because v1.2 has precision 2
fmt.Println(v1.EqualsOrNewer(v2))
// v1.2 does not match v1.3.0 because minor differs
fmt.Println(v1.EqualsOrNewer(v3))
Output: true false