# Go maps in action
6 Feb 2013
Tags: map, technical
Summary: How and when to use Go maps.
OldURL: /go-maps-in-action

Andrew Gerrand

## Introduction

One of the most useful data structures in computer science is the hash table.
Many hash table implementations exist with varying properties,
but in general they offer fast lookups, adds, and deletes.
Go provides a built-in map type that implements a hash table.

## Declaration and initialization

A Go map type looks like this:

	map[KeyType]ValueType

where `KeyType` may be any type that is [comparable](https://golang.org/ref/spec#Comparison_operators)
(more on this later),
and `ValueType` may be any type at all, including another map!

This variable `m` is a map of string keys to int values:

	var m map[string]int

Map types are reference types, like pointers or slices,
and so the value of `m` above is `nil`;
it doesn't point to an initialized map.
A nil map behaves like an empty map when reading,
but attempts to write to a nil map will cause a runtime panic; don't do that.
To initialize a map, use the built in `make` function:

	m = make(map[string]int)

The `make` function allocates and initializes a hash map data structure
and returns a map value that points to it.
The specifics of that data structure are an implementation detail of the
runtime and are not specified by the language itself.
In this article we will focus on the _use_ of maps,
not their implementation.

## Working with maps

Go provides a familiar syntax for working with maps. This statement sets the key `"route"` to the value `66`:

	m["route"] = 66

This statement retrieves the value stored under the key `"route"` and assigns it to a new variable i:

	i := m["route"]

If the requested key doesn't exist, we get the value type's _zero value_.
In this case the value type is `int`, so the zero value is `0`:

	j := m["root"]
	// j == 0

The built in `len` function returns on the number of items in a map:

	n := len(m)

The built in `delete` function removes an entry from the map:

	delete(m, "route")

The `delete` function doesn't return anything, and will do nothing if the specified key doesn't exist.

A two-value assignment tests for the existence of a key:

	i, ok := m["route"]

In this statement, the first value (`i`) is assigned the value stored under the key `"route"`.
If that key doesn't exist, `i` is the value type's zero value (`0`).
The second value (`ok`) is a `bool` that is `true` if the key exists in
the map, and `false` if not.

To test for a key without retrieving the value, use an underscore in place of the first value:

	_, ok := m["route"]

To iterate over the contents of a map, use the `range` keyword:

	for key, value := range m {
	    fmt.Println("Key:", key, "Value:", value)
	}

To initialize a map with some data, use a map literal:

	commits := map[string]int{
	    "rsc": 3711,
	    "r":   2138,
	    "gri": 1908,
	    "adg": 912,
	}

The same syntax may be used to initialize an empty map, which is functionally identical to using the `make` function:

	m = map[string]int{}

## Exploiting zero values

It can be convenient that a map retrieval yields a zero value when the key is not present.

For instance, a map of boolean values can be used as a set-like data structure
(recall that the zero value for the boolean type is false).
This example traverses a linked list of `Nodes` and prints their values.
It uses a map of `Node` pointers to detect cycles in the list.

.code maps/list.go /START/,/END/

The expression `visited[n]` is `true` if `n` has been visited,
or `false` if `n` is not present.
There's no need to use the two-value form to test for the presence of `n` in the map;
the zero value default does it for us.

Another instance of helpful zero values is a map of slices.
Appending to a nil slice just allocates a new slice,
so it's a one-liner to append a value to a map of slices;
there's no need to check if the key exists.
In the following example, the slice people is populated with `Person` values.
Each `Person` has a `Name` and a slice of Likes.
The example creates a map to associate each like with a slice of people that like it.

.code maps/people.go /START1/,/END1/

To print a list of people who like cheese:

.code maps/people.go /START2/,/END2/

To print the number of people who like bacon:

.code maps/people.go /bacon/

Note that since both range and len treat a nil slice as a zero-length slice,
these last two examples will work even if nobody likes cheese or bacon (however
unlikely that may be).

## Key types

As mentioned earlier, map keys may be of any type that is comparable.
The [language spec](https://golang.org/ref/spec#Comparison_operators)
defines this precisely,
but in short, comparable types are boolean,
numeric, string, pointer, channel, and interface types,
and structs or arrays that contain only those types.
Notably absent from the list are slices, maps, and functions;
these types cannot be compared using `==`,
and may not be used as map keys.

It's obvious that strings, ints, and other basic types should be available as map keys,
but perhaps unexpected are struct keys.
Struct can be used to key data by multiple dimensions.
For example, this map of maps could be used to tally web page hits by country:

	hits := make(map[string]map[string]int)

This is map of string to (map of `string` to `int`).
Each key of the outer map is the path to a web page with its own inner map.
Each inner map key is a two-letter country code.
This expression retrieves the number of times an Australian has loaded the documentation page:

	n := hits["/doc/"]["au"]

Unfortunately, this approach becomes unwieldy when adding data,
as for any given outer key you must check if the inner map exists,
and create it if needed:

	func add(m map[string]map[string]int, path, country string) {
	    mm, ok := m[path]
	    if !ok {
	        mm = make(map[string]int)
	        m[path] = mm
	    }
	    mm[country]++
	}
	add(hits, "/doc/", "au")

On the other hand, a design that uses a single map with a struct key does away with all that complexity:

	type Key struct {
	    Path, Country string
	}
	hits := make(map[Key]int)

When an Vietnamese person visits the home page,
incrementing (and possibly creating) the appropriate counter is a one-liner:

	hits[Key{"/", "vn"}]++

And it's similarly straightforward to see how many Swiss people have read the spec:

	n := hits[Key{"/ref/spec", "ch"}]

## Concurrency

[Maps are not safe for concurrent use](https://golang.org/doc/faq#atomic_maps):
it's not defined what happens when you read and write to them simultaneously.
If you need to read from and write to a map from concurrently executing goroutines,
the accesses must be mediated by some kind of synchronization mechanism.
One common way to protect maps is with [sync.RWMutex](https://golang.org/pkg/sync/#RWMutex).

This statement declares a `counter` variable that is an anonymous struct
containing a map and an embedded `sync.RWMutex`.

	var counter = struct{
	    sync.RWMutex
	    m map[string]int
	}{m: make(map[string]int)}

To read from the counter, take the read lock:

	counter.RLock()
	n := counter.m["some_key"]
	counter.RUnlock()
	fmt.Println("some_key:", n)

To write to the counter, take the write lock:

	counter.Lock()
	counter.m["some_key"]++
	counter.Unlock()

## Iteration order

When iterating over a map with a range loop,
the iteration order is not specified and is not guaranteed to be the same
from one iteration to the next.
If you require a stable iteration order you must maintain a separate data structure that specifies that order.
This example uses a separate sorted slice of keys to print a `map[int]string` in key order:

	import "sort"

	var m map[int]string
	var keys []int
	for k := range m {
	    keys = append(keys, k)
	}
	sort.Ints(keys)
	for _, k := range keys {
	    fmt.Println("Key:", k, "Value:", m[k])
	}
