Documentation
¶
Overview ¶
Package semver implements parsing of [Semantic Versions].
Index ¶
- Variables
- type Strict
- type Version
- func (v Version) Compare(w Version) int
- func (v Version) Equal(w Version) bool
- func (v Version) Go() string
- func (v Version) IsZero() bool
- func (v Version) LogValue() slog.Value
- func (v Version) MajorMinor() string
- func (v Version) MarshalText() (text []byte, err error)
- func (v Version) NextMajor() Version
- func (v Version) NextMinor() Version
- func (v Version) NextPatch() Version
- func (v Version) NextPreRelease(kind string) Version
- func (v Version) PreReleaseVersion() (kind string, n int, found bool)
- func (v Version) Release() Version
- func (v Version) String() string
- func (v *Version) UnmarshalText(text []byte) error
- func (v Version) WithBuild(parts ...string) Version
- func (v Version) WithPreRelease(parts ...any) Version
- func (v Version) WithPrefix(prefix string) string
Examples ¶
- Build
- ForModule
- Go
- MustParse
- MustParseStrict
- Parse
- ParseStrict
- Strict.UnmarshalText
- Version.Compare
- Version.Equal
- Version.Go
- Version.IsZero
- Version.LogValue
- Version.MajorMinor
- Version.MarshalText
- Version.NextMajor
- Version.NextMinor
- Version.NextPatch
- Version.NextPreRelease
- Version.PreReleaseVersion
- Version.Release
- Version.UnmarshalText
- Version.WithBuild
- Version.WithPreRelease
- Version.WithPrefix
Constants ¶
This section is empty.
Variables ¶
var ErrInvalidVersion = errors.New("invalid version")
ErrInvalidVersion is returned by Parse and ParseStrict when the given version number is invalid.
Functions ¶
This section is empty.
Types ¶
type Strict ¶
type Strict struct {
Version
}
Strict is a Version that unmarshals using ParseStrict instead of Parse.
func (*Strict) UnmarshalText ¶
UnmarshalText decodes a Semantic Version from its text-representation using ParseStrict. The text must be strictly valid SemVer.
It implements encoding.TextUnmarshaler.
Example ¶
package main
import (
"encoding/json"
"fmt"
"go.hofstra.dev/semver"
)
func main() {
var v semver.Strict
_ = json.Unmarshal([]byte(`"1.2.3-rc.1"`), &v)
fmt.Println(v)
}
Output: 1.2.3-rc.1
type Version ¶
type Version struct {
// Major version. Increments for backwards incompatible changes.
// Use [Version.NextMajor] to increment.
Major int
// Minor version. Increments for new (backwards compatible) features.
// Use [Version.NextMinor] to increment.
Minor int
// Patch version. Increments for backwards compatible bug-fixes.
// Use [Version.NextPatch] to increment.
Patch int
// Pre version. Indicates that the version is unstable.
// Use [Version.WithPreRelease] to set it to a sanitized value.
Pre string
// Build metadata. Informational only, and ignored for most operations.
// Use [Version.WithBuild] to set it ito a sanitized value.
Build string
}
A Version represents a Semantic Version. Use New, Version.WithPreRelease and Version.WithBuild to ensure that the field values are valid.
See the Semantic Version Specification for details on how these fields can be used.
It implements encoding.TextMarshaler, encoding.TextUnmarshaler, fmt.Stringer and slog.LogValuer.
func Build ¶
func Build() Version
Build returns the version of the main module corresponding to the debug.BuildInfo. It returns a zero version when go module support is disabled or the main version is invalid.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/semver"
)
func main() {
fmt.Println(semver.Build())
}
Output: 0.0.0+devel
func ForModule ¶
ForModule returns the version for the given module. It returns the zero version if the module version is invalid.
Example ¶
package main
import (
"fmt"
"runtime/debug"
"go.hofstra.dev/semver"
)
func main() {
v := semver.ForModule(debug.Module{
Path: "golang.org/x/exp",
Version: "v0.0.0-20260312153236-7ab1446f8b90",
})
fmt.Println(v)
v = semver.ForModule(debug.Module{
Path: "golang.org/x/sync",
Version: "v0.20.0",
})
fmt.Println(v)
v = semver.ForModule(debug.Module{
Path: "main",
Version: "(devel)",
})
fmt.Println(v)
}
Output: 0.0.0-20260312153236-7ab1446f8b90 0.20.0 0.0.0+devel
func Go ¶
func Go() Version
Go returns the version of the Go toolchain that built the binary. It may return the zero Version for a non-stable Go release.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/semver"
)
func main() {
fmt.Println(semver.Go())
}
Output:
func MustParse ¶
MustParse parses given version string using Parse. It panics where Parse returns an error.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/semver"
)
func main() {
v := semver.MustParse("v1.0.0-rc.1+build.1")
fmt.Println(v)
}
Output: 1.0.0-rc.1+build.1
func MustParseStrict ¶
MustParseStrict parses given version string using ParseStrict. It panics where ParseStrict returns an error.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/semver"
)
func main() {
v := semver.MustParseStrict("1.0.0-rc.1+build.1")
fmt.Println(v)
}
Output: 1.0.0-rc.1+build.1
func New ¶
New returns a Version with the given major, minor and patch versions. It panics if one of the given versions is negative.
func Parse ¶
Parse parses the given string as a Semantic Version. It does not strictly validate that the given version is valid, as it allows for several things that are not valid SemVer:
- It strips any prefix consisting of 'a-z', 'A-Z' and '_'.
- It allows for partial versions like '1' and '1.2'.
Use ParseStrict to only allow fully valid semantic versions.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/semver"
)
func main() {
versions := []string{
// These versions are valid semver.
"1.2.3",
"1.0.0-rc.1+build.1",
// These versions are not valid semver,
// but are accepted by Parse, but not by ParseStrict.
"v1.2.3",
"version1.2.3",
"go1.27",
"release_1.2.3",
}
for _, s := range versions {
v, _ := semver.Parse(s)
fmt.Printf("%-18s %#v\n", s, v)
}
}
Output: 1.2.3 semver.Version{Major:1, Minor:2, Patch:3, Pre:"", Build:""} 1.0.0-rc.1+build.1 semver.Version{Major:1, Minor:0, Patch:0, Pre:"rc.1", Build:"build.1"} v1.2.3 semver.Version{Major:1, Minor:2, Patch:3, Pre:"", Build:""} version1.2.3 semver.Version{Major:1, Minor:2, Patch:3, Pre:"", Build:""} go1.27 semver.Version{Major:1, Minor:27, Patch:0, Pre:"", Build:""} release_1.2.3 semver.Version{Major:1, Minor:2, Patch:3, Pre:"", Build:""}
func ParseStrict ¶
ParseStrict parses the given string as a Semantic Version. It must be strictly valid according to the SemVer specification.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/semver"
)
func main() {
// valid semver
v, _ := semver.ParseStrict("1.0.0-rc.1+build.1")
fmt.Println(v)
// not valid semver
_, err := semver.ParseStrict("v1.2.3")
fmt.Println(err)
}
Output: 1.0.0-rc.1+build.1 invalid version: major: invalid number: "v"
func (Version) Compare ¶
Compare compares the version v with w according the precedence rules in the SemVer spec. It returns -1 if v is before w, +1 if v is after w, and 0 if they are equal.
Example ¶
package main
import (
"fmt"
"slices"
"go.hofstra.dev/semver"
)
func main() {
versions := []semver.Version{
semver.MustParse("1.0.0-alpha.1"),
semver.MustParse("1.0.0-rc.1"),
semver.MustParse("1.0.0-beta"),
semver.MustParse("1.0.0-alpha.beta"),
semver.MustParse("1.0.0"),
semver.MustParse("1.0.0-beta.11"),
semver.MustParse("1.0.0-beta.11"),
semver.MustParse("1.0.0-alpha"),
semver.MustParse("1.0.0-beta.2"),
semver.MustParse("2.0.0"),
semver.MustParse("1.2.3"),
semver.MustParse("1.2.3"),
semver.MustParse("1.2.0"),
}
// sort the versions using the compare method
slices.SortFunc(versions, semver.Version.Compare)
for _, version := range versions {
fmt.Println(version)
}
}
Output: 1.0.0-alpha 1.0.0-alpha.1 1.0.0-alpha.beta 1.0.0-beta 1.0.0-beta.2 1.0.0-beta.11 1.0.0-beta.11 1.0.0-rc.1 1.0.0 1.2.0 1.2.3 1.2.3 2.0.0
func (Version) Equal ¶
Equal returns true if v is equal to w according the precedence rules in the SemVer spec. Use v == w for exact comparison.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/semver"
)
func main() {
a := semver.MustParse("1.0.0-rc.1+build.1")
b := semver.MustParse("1.0.0-rc.1+build.2")
c := semver.MustParse("1.0.0-rc.2+build.1")
fmt.Printf("%s eq %s -> %t\n", a, b, a.Equal(b))
fmt.Printf("%s eq %s -> %t\n", a, c, a.Equal(c))
}
Output: 1.0.0-rc.1+build.1 eq 1.0.0-rc.1+build.2 -> true 1.0.0-rc.1+build.1 eq 1.0.0-rc.2+build.1 -> false
func (Version) Go ¶
Go returns v as a Go module version string: a semantic version with a v prefix. This is equivalent to Version.WithPrefix("v"). See module version numbering for details.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/semver"
)
func main() {
v := semver.New(1, 2, 3)
fmt.Println(v.Go())
}
Output: v1.2.3
func (Version) IsZero ¶
IsZero returns true if the version is equivalent to the zero value. The version's build metadata is ignored.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/semver"
)
func main() {
versions := []semver.Version{
semver.MustParse("v0.0.0-20170915032832-14c0d48ead0c"),
semver.MustParse("v0.0.0+meta"),
semver.MustParse("v2.0.0"),
}
for _, v := range versions {
fmt.Printf("%s is zero: %t\n", v, v.IsZero())
}
}
Output: 0.0.0-20170915032832-14c0d48ead0c is zero: false 0.0.0+meta is zero: true 2.0.0 is zero: false
func (Version) LogValue ¶
LogValue returns the version for logging.
It implements slog.LogValuer.
Example ¶
package main
import (
"log/slog"
"os"
"go.hofstra.dev/semver"
)
func main() {
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
// Remove the timestamps from the logging so this example has consistent output.
ReplaceAttr: func(groups []string, a slog.Attr) slog.Attr {
if a.Key == slog.TimeKey && len(groups) == 0 {
return slog.Attr{}
}
return a
},
}))
logger.Info("Running",
"application", "my-app",
"version", semver.New(1, 2, 3))
}
Output: level=INFO msg=Running application=my-app version=1.2.3
func (Version) MajorMinor ¶
MajorMinor returns the major/minor version, eg: 1.2 for 1.2.3.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/semver"
)
func main() {
v := semver.New(1, 2, 3).WithPreRelease("rc", 1)
fmt.Println(v.MajorMinor())
}
Output: 1.2
func (Version) MarshalText ¶
MarshalText encodes the version to its text-representation.
It implements encoding.TextMarshaler.
Example ¶
package main
import (
"encoding/json"
"os"
"go.hofstra.dev/semver"
)
func main() {
v := semver.New(1, 2, 3).WithPreRelease("rc", 1)
_ = json.NewEncoder(os.Stdout).Encode(v)
}
Output: "1.2.3-rc.1"
func (Version) NextMajor ¶
NextMajor returns the next major version, with all other fields set to the zero value.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/semver"
)
func main() {
v := semver.New(1, 2, 3).WithPreRelease("rc", 1)
fmt.Println(v.NextMajor())
}
Output: 2.0.0
func (Version) NextMinor ¶
NextMinor returns the next minor version, with all other fields except for the major version set to the zero value.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/semver"
)
func main() {
v := semver.New(1, 2, 3).WithPreRelease("rc", 1)
fmt.Println(v.NextMinor())
}
Output: 1.3.0
func (Version) NextPatch ¶
NextPatch returns the next patch version, with the pre-release version and build metadata set to the zero value.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/semver"
)
func main() {
v := semver.New(1, 2, 3).WithPreRelease("rc", 1)
fmt.Println(v.NextPatch())
}
Output: 1.2.4
func (Version) NextPreRelease ¶
NextPreRelease returns the next pre-release version (starting at 1) for the kind of pre-release (alpha, beta, rc, etc). It removes all other pre-release information.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/semver"
)
func main() {
v := semver.New(1, 2, 3).NextPreRelease("rc")
fmt.Println(v)
v = v.NextPreRelease("rc")
fmt.Println(v)
}
Output: 1.2.3-rc.1 1.2.3-rc.2
func (Version) PreReleaseVersion ¶
PreReleaseVersion returns the pre-release version number and the kind of pre-release for the first pre-release component. Other pre-release components are ignored.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/semver"
)
func main() {
versions := []semver.Version{
semver.MustParse("1.0.0-alpha"),
semver.MustParse("1.0.0-alpha.1"),
semver.MustParse("1.0.0-alpha.beta"),
semver.MustParse("1.0.0-beta"),
semver.MustParse("1.0.0-beta.2"),
semver.MustParse("1.0.0-beta.11"),
semver.MustParse("1.0.0-beta.11"),
semver.MustParse("1.0.0-rc.1"),
semver.MustParse("1.0.0"),
}
for _, v := range versions {
kind, n, found := v.PreReleaseVersion()
fmt.Printf("%-5s %2d %t\n", kind, n, found)
}
}
Output: alpha 0 true alpha 1 true 0 false beta 0 true beta 2 true beta 11 true beta 11 true rc 1 true 0 false
func (Version) Release ¶
Release returns the version without pre-release or build identifiers.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/semver"
)
func main() {
v := semver.New(1, 2, 3).WithPreRelease("rc", 1)
fmt.Println(v.Release())
}
Output: 1.2.3
func (*Version) UnmarshalText ¶
UnmarshalText decodes a Semantic Version from its text-representation using Parse. The text does not have to be strictly valid SemVer.
It implements encoding.TextUnmarshaler.
Example ¶
package main
import (
"encoding/json"
"fmt"
"go.hofstra.dev/semver"
)
func main() {
var v semver.Version
_ = json.Unmarshal([]byte(`"1.2.3-rc.1"`), &v)
fmt.Println(v)
}
Output: 1.2.3-rc.1
func (Version) WithBuild ¶
WithBuild returns the version with the build metadata set to contain the given parts (string or int). It sanitizes parts in order to ensure valid build metadata as follows:
- Invalid characters are escaped as '-'.
- Empty parts ("") are omitted.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/semver"
)
func main() {
v := semver.New(1, 2, 3)
// set the build info, note that empty, emoji and '.' are not valid
v = v.WithBuild("a", "", "b", "💔", "c.d")
fmt.Println(v)
}
Output: 1.2.3+a.b.-.c-d
func (Version) WithPreRelease ¶
WithPreRelease returns the version with the pre-release version set to contain the given parts (string or int). It sanitizes parts in order to ensure a valid pre-release version as follows:
- Invalid characters are escaped as '-'.
- Empty parts ("") are omitted.
- The leading zero is removed from numbers (e.g. "0123" becomes "123").
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/semver"
)
func main() {
v := semver.New(1, 2, 3)
// set the pre-release version, note that empty, leading zeroes, emoji and '.' are not valid
v = v.WithPreRelease("a", "", "01", 2, "💔", "c.d")
fmt.Println(v)
}
Output: 1.2.3-a.1.2.-.c-d
func (Version) WithPrefix ¶
WithPrefix returns the string representation of v prepended with the given prefix.
Example ¶
package main
import (
"fmt"
"go.hofstra.dev/semver"
)
func main() {
v := semver.New(1, 2, 3).WithPreRelease("rc", 1)
fmt.Println(v.WithPrefix("version"))
}
Output: version1.2.3-rc.1