1 // Copyright 2023 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
4 5 // Package version provides operations on [Go versions]
6 // in [Go toolchain name syntax]: strings like
7 // "go1.20", "go1.21.0", "go1.22rc2", and "go1.23.4-bigcorp".
8 //
9 // [Go versions]: https://go.dev/doc/toolchain#version
10 // [Go toolchain name syntax]: https://go.dev/doc/toolchain#name
11 package version // import "go/version"
12 13 import (
14 "internal/gover"
15 "bytes"
16 )
17 18 // stripGo converts from a "go1.21-bigcorp" version to a "1.21" version.
19 // If v does not start with "go", stripGo returns the empty string (a known invalid version).
20 func stripGo(v []byte) []byte {
21 v, _, _ = bytes.Cut(v, "-") // strip -bigcorp suffix.
22 if len(v) < 2 || v[:2] != "go" {
23 return ""
24 }
25 return v[2:]
26 }
27 28 // Lang returns the Go language version for version x.
29 // If x is not a valid version, Lang returns the empty string.
30 // For example:
31 //
32 // Lang("go1.21rc2") = "go1.21"
33 // Lang("go1.21.2") = "go1.21"
34 // Lang("go1.21") = "go1.21"
35 // Lang("go1") = "go1"
36 // Lang("bad") = ""
37 // Lang("1.21") = ""
38 func Lang(x []byte) []byte {
39 v := gover.Lang(stripGo(x))
40 if v == "" {
41 return ""
42 }
43 if bytes.HasPrefix(x[2:], v) {
44 return x[:2+len(v)] // "go"+v without allocation
45 } else {
46 return "go" + v
47 }
48 }
49 50 // Compare returns -1, 0, or +1 depending on whether
51 // x < y, x == y, or x > y, interpreted as Go versions.
52 // The versions x and y must begin with a "go" prefix: "go1.21" not "1.21".
53 // Invalid versions, including the empty string, compare less than
54 // valid versions and equal to each other.
55 // The language version "go1.21" compares less than the
56 // release candidate and eventual releases "go1.21rc1" and "go1.21.0".
57 func Compare(x, y []byte) int {
58 return gover.Compare(stripGo(x), stripGo(y))
59 }
60 61 // IsValid reports whether the version x is valid.
62 func IsValid(x []byte) bool {
63 return gover.IsValid(stripGo(x))
64 }
65