go-version is a library for parsing versions and version constraints, and verifying versions against a set of constraints. go-version can sort a collection of versions properly, handles prerelease versions, etc.
go-version provides two packages:
- semver
- Semantic Versioning
- MAJOR.MINOR.PATCH-PRERELEASE+BUILDMETADATA (e.g. 1.1.3-alpha+110)
- version
- Semantic Versioning like versioning
- Accept more than 3 numbers (e.g. 2.3.1.4)
Versions used with semver
package must follow Semantic Versioning.
When two versions are compared using functions such as Compare, LessThan, and others, it will follow the specification and always include pre-releases within the comparison. It will provide an answer that is valid with the comparison section of the spec.
See example
v1, _ := semver.Parse("1.2.0")
v2, _ := semver.Parse("1.2.1")
// Comparison example. There is also GreaterThan, Equal, and just
// a simple Compare that returns an int allowing easy >=, <=, etc.
if v1.LessThan(v2) {
fmt.Printf("%s is less than %s", v1, v2)
}
It follows the spec.
See example
versionsRaw := []string{"1.1.0", "0.7.1", "1.4.0", "1.4.0-alpha", "1.4.1-beta", "1.4.0-alpha.2+20130313144700"}
versions := make([]semver.Version, len(versionsRaw))
for i, raw := range versionsRaw {
v, _ := semver.Parse(raw)
versions[i] = v
}
// After this, the versions are properly sorted
sort.Sort(semver.Collection(versions))
Comma-separated version constraints are considered an AND
.
For example, ">= 1.2.3, < 2.0.0" means the version needs to be greater than or equal to 1.2 and less than 3.0.0.
In addition, they can be separated by || (OR)
.
For example, ">= 1.2.3, < 2.0.0 || > 4.0.0" means the version needs to be greater than or equal to 1.2 and less than 3.0.0, or greater than 4.0.0.
See example
v, _ := semver.Parse("2.1.0")
c, _ := semver.NewConstraints(">= 1.0, < 1.4 || > 2.0")
if c.Check(v) {
fmt.Printf("%s satisfies constraints '%s'", v, c)
}
Supported operators
=
: you accept that exact version!=
: not equal>
: you accept any version higher than the one you specify>=
: you accept any version equal to or higher than the one you specify<
: you accept any version lower to the one you specify<=
: you accept any version equal or lower to the one you specify^
: it will only do updates that do not change the leftmost non-zero number.- e.g.
^1.2.3
:=>=1.2.3, <2.0.0
- e.g.
~
: allows patch-level changes if a minor version is specified on the comparator. Allows minor-level changes if not.- e.g.
~1.2.3
:=>=1.2.3, <1.3.0
- e.g.
^
and ~
work like npm
. See here.
As for version constraints, there are a few caveats since the constraints are not part of the specification.
- Pre-release
- Missing major/minor/patch versions
A pre-release version may be denoted by appending a hyphen and a series of dot separated identifiers immediately following the patch version. Pre-release versions have a lower precedence than the associated normal version (e.g. 1.2.3-alpha < 1.2.3). A pre-release version indicates that the version is unstable and might not satisfy the intended compatibility requirements as denoted by its associated normal version.
semver
comparisons using constraints without a prerelease comparator will skip prerelease versions.
For example, >=1.2.3 will skip pre-releases when looking at a list of releases.
In the following example, 2.1.0-alpha
looks greater than 2.0.0
, but c.Check(v)
returns false.
v, _ := semver.Parse("2.1.0-alpha")
c, _ := semver.NewConstraints(">= 2.0.0")
c.Check(v) // false
Constraints with a prerelease comparator will include prerelease versions.
v, _ := semver.Parse("2.1.0-alpha")
c, _ := semver.NewConstraints(">= 2.0.0-alpha")
c.Check(v) // true
Note that this is different from the behavior of npm.
>= 2.0.0-alpha
allows pre-releases in the 2.0.0 version only, if they are greater than or equal to alpha.
So, 2.0.0-beta would be allowed, while 2.1.0-alpha would not.
You can use go-npm-version for npm version comparion.
It strictly follows the npm rules.
If you want to include pre-releases even with no pre-releases constraint, you can pass semver.WithPreRelease(true)
as an argument of semver.NewConstraints
v, _ := semver.Parse("2.1.0-alpha")
c, _ := semver.NewConstraints(">= 2.0.0", semver.WithPreRelease(true))
c.Check(v) // true
If some of major/minor/patch versions are not specified, it is treated as *
by default.
In short, 3.1.3
satisfies = 3
because = 3
is converted to = 3.*.*
.
v, _ := semver.Parse("2.3.4")
c, _ := semver.NewConstraints("= 2")
c.Check(v) // true
Then, 2.2.3
doesn't satisfy > 2
as > 2
is treated as > 2.*.*
= >= 3.0.0
v, _ := semver.Parse("2.2.3")
c, _ := semver.NewConstraints("> 2")
c.Check(v) // false
3.3.9
satisifies = 3.3
, and 5.1.2
doesn't satisfy > 5.1
likewise.
If you want to treat them as 0, you can pass semver.WithZeroPadding(true)
as an argument of semver.NewConstraints
v, _ := semver.Parse("2.3.4")
c, _ := semver.NewConstraints("= 2", semver.WithZeroPadding(true))
c.Check(v) // false
Versions used with version
package follows Semantic Versioning like versioning.
It accepts more than 3 numbers such as 2.2.4.3
.
It works almost as well as semver
package. It also accepts pre-release and build metadata.
When two versions are compared using functions such as Compare, LessThan, and others, it will follow the specification and always include pre-releases within the comparison.
See example
v1, _ := version.Parse("1.2.0.9-alpha")
v2, _ := version.Parse("1.2.1.0+11")
// Comparison example. There is also GreaterThan, Equal, and just
// a simple Compare that returns an int allowing easy >=, <=, etc.
if v1.LessThan(v2) {
fmt.Printf("%s is less than %s\n", v1, v2)
}
It also supports version sorting.
It is almost the same as semver
package, but there are some differences.
See example
v, _ := version.Parse("2.1.0.1-alpha")
c, _ := version.NewConstraints(">= 1.0, < 1.4 || > 2.1")
if c.Check(v) {
fmt.Printf("%s satisfies constraints '%s'", v, c)
}
Supported operators:
=
: you accept that exact version!=
: not equal>
: you accept any version higher than the one you specify>=
: you accept any version equal to or higher than the one you specify<
: you accept any version lower to the one you specify<=
: you accept any version equal or lower to the one you specify^
: it will only do updates that do not change the leftmost non-zero number.- e.g.
^1.2.3
:=>=1.2.3, <2.0.0
- e.g.
~
: allows patch-level changes if a minor version is specified on the comparator. Allows minor-level changes if not.- e.g.
~1.2.3
:=>=1.2.3, <1.3.0
- e.g.
~>
: you accept any version equal to or greater than in the last digit- e.g.
~>3.0.3
:=>= 3.0.3, < 3.1
- e.g.
NOTE : version
package doesn't support wildcards such as x
, X
, and *
.
Unlike the semver
package, version
package always includes pre-release versions even with no pre-releases constraint.
v, _ := version.Parse("2.1.0.1-alpha")
c, _ := version.NewConstraints("> 2.0.0")
c.Check(v) // true
Unlike the semver
package, version
package fills in the missing versions with 0.
In short, 3.1.3
doesn't satisfy = 3
because = 3
is converted to = 3.0.0
.
v, _ := version.Parse("3.1.3")
c, _ := version.NewConstraints("= 3")
c.Check(v) // false
The x, X, and * characters can be used as a wildcard character. This works for all comparison operators. When used on the = operator it falls back to the patch level comparison (see tilde below). For example,
2.0.x
:=>= 2.0.0, < 2.1.0
>= 1.2.x
:=>= 1.2.0
<= 3.x
:=< 4.0.0
*
:=>= 0.0.0
Allows patch-level changes if a minor version is specified on the comparator. Allows minor-level changes if not. If it consists of more than 3 numbers, it allows changes that increases the last revision number.
~1.2.3
:=>=1.2.3 <1.(2+1).0
:=>=1.2.3 <1.3.0
~1.2
:=>=1.2.0 <1.(2+1).0
:=>=1.2.0 <1.3.0
(Same as1.2.x
)~1
:=>=1.0.0 <(1+1).0.0
:=>=1.0.0 <2.0.0
(Same as1.x
)~0.2.3
:=>=0.2.3 <0.(2+1).0
:=>=0.2.3 <0.3.0
~0.2
:=>=0.2.0 <0.(2+1).0
:=>=0.2.0 <0.3.0
(Same as0.2.x
)~0
:=>=0.0.0 <(0+1).0.0
:=>=0.0.0 <1.0.0
(Same as0.x
)~1.2.3-beta.2
:=>=1.2.3-beta.2 <1.3.0
~0.0.0.4
:=>=0.0.0.4 <0.0.1
Allows changes that do not modify the left-most non-zero digit.
^1.2.3
:=>=1.2.3 <2.0.0
^0.2.3
:=>=0.2.3 <0.3.0
^0.0.3
:=>=0.0.3 <0.0.4
^1.2.3-beta.2
:=>=1.2.3-beta.2 <2.0.0
^0.0.0.4
:=>=0.0.0.4 <0.0.0.5
It means the version must be equal to or greater than in the last digit.
~>1.2.3
:=>=1.2.3 <1.3.0
~>1.2
:=>=1.2.0 <2.0
(different from~
)~>1
:=>=1.0.0 <2.0.0
~>1.2.3-beta.2
:=>=1.2.3-beta.2 <1.3.0
~>0.0.0.4
:=>=0.0.0.4 <0.0.1