Skip to main content
  1. Articles/

Golang Release 1.22: version

·823 words·4 mins· loading · loading ·
Marko Milojevic
Author
Marko Milojevic
Software engineer and architect. Golang and LLM enthusiast. Awful chess player, gym rat, harmonica newbie and cat lover.
New features in Golang - This article is part of a series.
Part 5: This Article

With the release of Go 1.22, the Go standard library introduced several new features. As you might have noticed in articles related to the previous release, here we mostly concentrate on the new exciting packages and features that they give us. This article will start this journey, by providing a deeper look into the implementation of the version package in Go.

Lang
#

The first function we are ready to examine is the Lang function. This function provides a cleaned, valid Go version as a string. In case it can’t determine the actual version, due to an invalid state of the string value, it will return an string as a result.

Lang function

func Lang(x string) string

As we can see the function signature above, function expects one argument, a string, that represents a Go version. An output should be also one value, a string, as a cleaned Go version.

Lang function examples

package main

import (
	"fmt"
	"go/version"
)

func main() {
	fmt.Println(version.Lang("go1.0"))      // go1
	fmt.Println(version.Lang("go1"))        // go1
	fmt.Println(version.Lang("go1.22.4"))   // go1.22
	fmt.Println(version.Lang("go1.22.3"))   // go1.22
	fmt.Println(version.Lang("go1.22.2"))   // go1.22
	fmt.Println(version.Lang("go1.22.rc1")) //
	fmt.Println(version.Lang("go1.22rc1"))  // go1.22
	fmt.Println(version.Lang("1.22"))       //
	fmt.Println(version.Lang("wrong"))      //
	fmt.Println(version.Lang(""))           //
}

In the example above, we can see how the Lang function adapt the Go version string. It removes all minor versions and appearance of “release candide” phrase, and present them in the end as an official Go versions that we experienced in the past (and we might experience in the future). In cases where we provided an invalid, or empty string, the ending result will be also an empty string, as the Lang function can’t find the actual version name.

One interesting point, not just for the Long function, but, as you will see, for all functions in this package, to consider some string as a valid Go version, it needs to have a prefix go.

IsValid
#

The next function we are examining is the IsValid function. This function checks a string with a potential Go version and returns a boolean result that tells us if the version is valid or not.

IsValid function

func IsValid(x string) bool

As we can see the function signature above, function expects one argument, a string, that represents a Go version. An output should be a bool value, which tells us if the Go version is valid or not.

IsValid function examples

package main

import (
	"fmt"
	"go/version"
)

func main() {
	fmt.Println(version.IsValid("go1.0"))      // true
	fmt.Println(version.IsValid("go1"))        // true
	fmt.Println(version.IsValid("go1.22.4"))   // true
	fmt.Println(version.IsValid("go1.22.3"))   // true
	fmt.Println(version.IsValid("go1.22.2"))   // true
	fmt.Println(version.IsValid("go1.22.rc1")) // false
	fmt.Println(version.IsValid("go1.22rc1"))  // true
	fmt.Println(version.IsValid("1.22"))       // false
	fmt.Println(version.IsValid("wrong"))      // false
	fmt.Println(version.IsValid(""))           // false
}

In the example above, we can see how the IsValid function checks validity of Go version string. In a way it represents a subcase of the Lang function: wherever we got an empty string in the Lang function, we got false as the result of the IsValid function.

Compare
#

Finally, with the function Compare, we are showing the complete picture of the version package. This function provides the complex functionality for comparing different Go version in a spirit of other examples of the Compare function.

Compare function

// Compare returns
//
//	-1 if x is less than y,
//	 0 if x equals y,
//	+1 if x is greater than y.
// ...
func Compare(x, y string) int

In the function signature, we can see that the Compare function accepts two strings as arguments, where both of them represent Go versions. The result is an integer value, which can be -1, 0 or 1, depending od the comparison result.

Compare function examples

package main

import (
	"fmt"
	"go/version"
)

func main() {
	fmt.Println(version.Compare("go1.0", "go1"))           // 0
	fmt.Println(version.Compare("go1.1", "go1.1.0"))       // 0
	fmt.Println(version.Compare("go1", ""))                // 1
	fmt.Println(version.Compare("", ""))                   // 0
	fmt.Println(version.Compare("", "go1"))                // -1
	fmt.Println(version.Compare("go1.22.4", "go1.22.3"))   // 1
	fmt.Println(version.Compare("go1.22.2", "go1.22.3"))   // -1
	fmt.Println(version.Compare("go1.22.2", "go1.22rc1"))  // 1
	fmt.Println(version.Compare("go1.22rc2", "go1.22rc1")) // 1
	fmt.Println(version.Compare("go1.22.4", "go1.21.4"))   // 1
	fmt.Println(version.Compare("go1.22rc1", "go1.22rc1")) // 1
}

In the examples above, we can see how the Compare function actually works. First, it can find equality for two same versions, even if they are written in a different ways (the first two examples). Second, we can see that invalid versions are always considered as lower versions than any valid ones. So, we should be careful here with the comparison, as initial version validation might be important to do.

Finally, for the correct versions, the Compare function is able to determine which one of them is a higher one, and provides such a result. This is not only applied for minor versions, but also for release candidate versions, as we can see in the last examples.

Conclusion
#

New version of Golang, 1.22, delivered many new updates, affecting standard library as well. In this article we checked how some functions from version packages work. Those new functions give us now possibility to validate and compare different Go version strings.

Useful Resources
#

New features in Golang - This article is part of a series.
Part 5: This Article

Related

Golang Release 1.21: slices - Part 1

·1939 words·10 mins· loading · loading
As part of the new Go release, several exciting changes have been introduced to the Go ecosystem. While we’ve explored some of these changes in other articles about the maps package and the cmp package, there’s much more to discover beyond these two packages. In this article, we’ll focus on the first part of the slices package, specifically its new search functionality. Like many other updates and newly introduced packages, this one is also built upon the foundation of generics, which were introduced in Go 1.18. BinarySearch and BinarySearchFunc # Let’s start by exploring the first pair of functions designed for efficiently searching a target value within sorted slices. In this context, we’re referring to the well-known Binary Search algorithm, which is renowned as one of the most significant algorithms and is frequently used in coding interviews. Below, you’ll find the signatures of both of these functions: BinarySearch function func BinarySearch[S ~[]E, E cmp.Ordered](x S, target E) (int, bool) BinarySearchFunc function func BinarySearchFunc[S ~[]E, E, T any](x S, target T, cmp func(E, T) int) (int, bool) Looking at the signatures of both functions, we can identify some small differences between them, and these differences serve specific purposes. The first function, BinarySearch, expects two arguments. The first argument should be a slice of sorted items, and it must adhere to the Ordered constraint. When the items are ordered, the algorithm can efficiently compare them using the Compare function from the cmp package. On the other hand, the second function, BinarySearchFunc, is more versatile. It allows searching within slices where the items don’t necessarily conform to the Ordered constraint. This flexibility is achieved by introducing a third argument, the comparison function. This function is responsible for comparing items and determining their order. It will be called by the BinarySearchFunc itself to make comparisons. Both functions return two values. The first value is the index of the item within the slice, and the second is a boolean value indicating whether the item was found in the slice or not. Let’s explore some examples below: BinarySearch examples fmt.Println(slices.BinarySearch([]int{1, 3, 5, 6, 7}, 5)) // Output: // 2 true fmt.Println(slices.BinarySearch([]int{1, 3, 5, 6, 7}, 9)) // Output: // 5 false fmt.Println(slices.BinarySearch([]int{1, 3, 5, 6, 7}, -5)) // Output: // 0 false fmt.Println(slices.BinarySearch([]string{"1", "3", "5", "6", "7"}, "5")) // Output: // 2 true fmt.Println(slices.BinarySearch([]string{"1", "3", "5", "6", "7", "8"}, "9")) // Output: // 6 false fmt.Println(slices.BinarySearch([]string{"1", "3", "5", "6", "7"}, "4")) // Output: // 2 false Take a close look at the results returned by the BinarySearch function, especially when the item doesn’t exist in the slice. In our examples, we encountered four such cases where the function returned 0, 2, 5, and 6. When the requested item isn’t present in the slice, the function indicates where it should be positioned if it were to be added to the slice. Since the slice is sorted, it’s possible to determine the appropriate position for the item within the slice.

Golang Release 1.21: cmp

·789 words·4 mins· loading · loading
As the new release of Go came this summer, many of us started to look for the improvements inside its ecosystem. Many new features were introduced, including updates to the tool command to support backward and forward compatibility. New packages appeared inside the Standard Library, including maps and slices. In this article we are covering improvements introduced with the new cmp package. The new package offers three new functions. All of them rely on Generics, a feature introduced in Go version 1.18, which has opened up possibilities for many new features. The cmp package introduces new functions for comparing values of Ordered constraint. Let’s dive into each of them. Ordered constraint and Compare function # The constraint Ordered encompasses all types that support comparison operators for values, specifically, <, <=, >= and >. This includes all numeric types in Go, as well as strings. Ordered Constraint type Ordered interface { ~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64 | ~string } Once we understand what the Ordered constraint includes, we can focus on the first function from the cmp package, which is the Compare function. Below, you can find its signature: Compare Function // Compare returns // // -1 if x is less than y, // 0 if x equals y, // +1 if x is greater than y. // ... func Compare[T Ordered](x, y T) int The signature, along with the function description, makes it much easier to understand. The Compare function expects two arguments of the same type, compares their values, and returns a result that represents the comparison status: -1 if the first argument is less than the second. 0 if the arguments’ values are equal. 1 if the first argument is greater than the second. Let’s prove such claim: Compare numerals fmt.Println(cmp.Compare(1, 2)) // Output: // -1 fmt.Println(cmp.Compare(1, 1)) // Output: // 0 fmt.Println(cmp.Compare(2, 1)) // Output: // 1 Compare strings fmt.Println(cmp.Compare("abc", "def")) // Output: // -1 fmt.Println(cmp.Compare("qwe", "qwe")) // Output: // 0 fmt.Println(cmp.Compare("abcde", "abcc")) // Output: // 1 Above, we can see practical examples of the Compare function for both numerals and strings. Indeed, the return values can only belong to the set of numbers {-1, 0, 1}, as defined in the description. Function Less # In addition to the function Compare, we got another, similar function Less. Although it’s rather easy to understand what is used for, let’s check its signature:

Golang Release 1.21: slices - Part 2

·2301 words·11 mins· loading · loading
With the release of Go 1.21, the Go standard library introduced several new features. While we’ve already discussed some of them in previous articles, in this episode, we’ll dive into more advanced enhancements. Naturally, we’ll focus on the new functions designed for sorting slices, which are part of the new slices package. This article will provide a deeper look into the implementation of these three new functions and touch on benchmarking as well. Sort # The Sort function is the first one we’d like to explore. This implementation is built upon the enhanced Pattern-defeating Quicksort, positioning it as one of the best-known unstable sorting algorithms. Don’t worry; we will discuss this “instability” aspect in this article. But first, let’s take a look at the function’s signature: Sort function func Sort[S ~[]E, E cmp.Ordered](x S) As we’ve seen in some other articles, nearly all improvements in the Go standard library are built upon generics, a feature introduced in Go version 1.18, almost three years ago. Similar to other functions, the Sort function also expects a slice of a generic type as an argument, where each item must adhere to the Ordered constraint. The function doesn’t return a new value but sorts the original slice in place. Below, you’ll find some basic examples: Sort function examples ints := []int{1, 2, 3, 5, 5, 7, 9} slices.Sort(ints) fmt.Println(ints) // Output: // 1 2 3 5 5 7 9 ints2 := []int{9, 7, 5, 5, 3, 2, 1} slices.Sort(ints2) fmt.Println(ints2) // Output: // 1 2 3 5 5 7 9 floats := []float64{9, 3, 5, 7, 1, 2, 5} slices.Sort(floats) fmt.Println(floats) // Output: // 1 2 3 5 5 7 9 strings := []string{"3", "9", "2", "5", "1", "7", "5"} slices.Sort(strings) fmt.Println(strings) // Output: // 1 2 3 5 5 7 9 In the example above, we can observe the result of the Sort method. All the outputs consist of sorted slices, arranged in ascending order. However, what makes this function particularly intriguing is its ability to handle various data types using a single function, distinguishing it from the implementations we already possess in the sort package. Now that we’ve examined the results, let’s proceed to compare the performance benchmarks with the existing package. Benchmark # In this section, we aim to evaluate the performance of the new function by comparing it to the already existing sort package. Below, you’ll find the benchmark test results: