The Avid Gopher

Extracting Keys of a map

As in many other languages even in Go the map is a very frequently used data-type used for a broad variety of purposes. For many of the use-cases you need access to a map’s keys.

The Problem

At times we need to resolve a slice of keys from one of your maps to process them further. A simple one might look like this:

1
2
3
4
myMap := map[string]string{
	"Foo": "Bar",
	"Baz": "Qux",
}

Captain Obvious led us to the subsequent line when trying to resolve our maps’ keys:

1
myMap.keys()

But, oh, Captain Obvious lied to us, obviously:

1
prog.go:14:7: myMap.keys undefined (type map[string]string has no field or method keys)

Ok, we have to dig deeper somehow as our intuition is not helpful that much.

The Solution

After some research we come up with another somehow naive but working solution:

1
2
3
4
5
6
7
8
package main

func main() {
    keys := make([]string, 0)
    for key := range myMap {
        keys = append(keys, key)
    }
}

“Oh man, It works! Why should this even be naive?” you might ask. Let me explain.

As keys is declared as a slice with zero length, each append of a key will lead to a very costly allocation of additional memory.

So, as we already know the size of the original map, let’s allocate the required amount of memory upfront by setting the capacity of keys which will speed things up:

1
2
3
4
5
6
7
8
package main

func main() {
    keys := make([]string, 0, len(myMap))
    for k := range myMap {
        keys = append(keys, k)
    }
}

This looks much better. Although setting the capacity eliminates reallocations when appending, append still has to do some extra lifting as it needs to check if we are exceeding the initial capacity which results in a performance penalty, too.

A more efficient approach

It is better to avoid the use of append as this eliminates any hidden memory allocation magic.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package main

func main() {
    keys := make([]string, len(myMap))
    i := 0
    for k := range mymap {
        keys[i] = k
        i++
    }
}

Result

This optimisations won’t make much of a difference as long as we are dealing with a hand full of items. But as soon as the map grows above a noticeably amount of items the processing-time will jump up.