Go Generics Improvements for Maps and Slices

Generic programming enables the creation of algorithms without specifying data types upfront.

Go introduced generics with the 1.18 release. Initially, I wasn’t particularly enthused about the addition of generics in Go. In my 10 years of using Go, whenever I needed to work with various types, interfaces and the reflect package met my requirements. Generics didn’t feel like something I needed in my daily work. However, the 1.20 release of Go added comparable types, expanding the utilities of generics. With this new semantic, the Go developers introduced two new packages: golang.org/x/exp/slices and golang.org/x/exp/maps.

I am excited about these new packages; they simplify working with maps & slices, and enhance execution efficiency. How? For example, with the new maps package, you can do the following:

package main

import (
	"fmt"
	"golang.org/x/exp/maps"
)

func main() {
	var myMap = map[interface{}]interface{}{
		"one": 1,
		2:     "two",
	}
	var copy = maps.Clone(myMap)
	fmt.Println(maps.Equal(myMap, copy))
}

In this example, copying the initial map and comparing pairs of maps are easily understandable and straightforward to write.

Previously, one would have to implement the maps.Clone and maps.Equal functions for each specific map type, or rely on reflect.Copy and reflect.DeepEqual. The functions from the maps package are both user-friendly and more efficient.

These improvements extend to slices with slices.Clone and slices.Equal. I’m happy to see the addition of functions such as slices.Min and slices.Max. Over the years, I’ve had to implement min or max functions for various slice types, and now, I don’t have to.

These enhancements will make the Go developer experience nicer. Generics made Golang more competitive with Rust and its powerful zero-cost abstractions.

Since the 1.21 release, the packages slices and maps are built into the standard library.

Go life was good, and it’s getting better.