When you look at Go code, you will encounter Slices and Maps everywhere. Both data types are simple and have characteristics that make them pivotal for myriads of different algorithms, as well as for general use.

Slices allow you to iterate through their values in order since they store the data sequentially.

Maps, on the other hand, don’t necessarily store their data in order. However, they do provide really fast lookups: O(1) (at least for fixed-size maps).

Their usefulness is undeniable but…

what if we could combine both?

In this tutorial, we’ll be learning the bare bone basics of Generics in Go 2. This feature will be a game-changer. We’ll be harnessing the power of Generics to create an OrderedMap type.

An OrderedMap combines the power of both a slice and map!

You might be thinking that an OrderedMap is already possible today. Yes, but we’ll be making a statically-typed OrderedMap, which means that we get strong type checking from the compiler and linter.

Generics has been the most sought after feature for Go since inception.

The Go 2 playground has been available for a few months now. It’s available here so you can follow along.

The current Generics proposal is available here.

NOTE: The draft proposal is changing rapidly.

Step 1: A perfect OrderedMap

What would the perfect OrderedMap look like? I wrote down 5 characteristics that we will strive to implement.

  1. It should look like this: map[KeyType]ValueType
  2. It should retrieve a value like this: val, exists := m["route"]
  3. It should set a value for a unique key like this: m["route"] = 66
  4. It should delete a key and its associated value like this: delete(m, "route")
  5. It should iterate like this: for key, value := range m {} where the order is based on the order in which the key-value pair was inserted.

Unfortunately, Generics, as currently proposed, will not be able to perfectly match the syntax above. Only changes to the Go specs can. But we can get the next best thing.

It can be seen from #1 that the OrderedMap can contain only one arbitrary data type for the key and value. It could be string-int pairs or float64-interface{} pairs for example. That is what is meant by statically typed.

Under Go 1, the best we could do is implement an interface{}-interface{} ordered map, where we will need to type-assert the stored value before we can use it. We also lose type checking from the compiler.

Alternatively, we need to use a code-generator to duplicate code for different data type pairs under a different name. eg OrderedMapStringInt and OrderedMapFloat64Mixed.

#generic-programming #generics #go #golang #go2

Ordered Maps for Go 2 (Using Generics)
1.25 GEEK