12. Maps

A Go map is a built-in unordered collection of key-value pairs. Also known as an associative array, a hash table or a dictionary, maps are used to look up a value by its associated key.

To create an empty map, use the built-in make:

1 make(map[key-type]val-type)

Note that the key can be an int, a float, complex number, string, pointer, even an interface that supports equality. We’ll look at interfaces later. We can also have a map like map[string]map[string]string. This is a map of strings to maps of strings to strings.

Let us look at the following Go program:

Program: maps.go


 1 package main
 2 
 3 import "fmt"
 4 
 5 func main() {
 6         m := make(map[string]int)
 7 
 8         //Set key/value pairs using typical
 9         //name[key] = val syntax
10         m["k1"] = 7
11         m["k2"] = 13
12 
13         //Printing a map with e.g. Println
14         //will show all of its key/value pairs
15         fmt.Println("map:", m)
16 
17         //Get a value for a key with name[key]
18         v1 := m["k1"]
19         fmt.Println("v1: ", v1)
20 
21         //The builtin len returns the number of
22         //key/value pairs when called on a map
23         fmt.Println("len:", len(m))
24 
25         //The builtin delete removes key/value pairs
26         //from a map
27         delete(m, "k2")
28         fmt.Println("map:", m)
29 
30         //The optional second return value when getting
31         //a value from a map indicates if the key was
32         //present in the map. This can be used to
33         //disambiguate between missing keys and keys
34         //with zero values like 0 or ""
35         _, prs := m["k2"]
36         fmt.Println("prs:", prs)
37 
38         //You can also declare and initialize a new map
39         //in the same line with this syntax
40         n := map[string]int{"foo": 1, "bar": 2}
41         fmt.Println("map:", n)
42 }

The output of the program is:

map: map[k1:7 k2:13]
v1:  7
len: 2
map: map[k1:7]
prs: false
map: map[foo:1 bar:2]

Note: x := make(map[int]int) looks very much like an array but there are a few differences. First the length of a map (found by doing len(x)) can change as we add new items to it. When first created it has a length of 0, after x[1] = 10 it has a length of 1. Second, maps are not sequential. We have x[1], and with an array that would imply there must be an x[0], but maps don’t have this requirement.

Remember:

Using nil slices and maps

It’s OK to add items to a nil slice, but doing the same with a map will produce a runtime panic.

package main

import "fmt"

func main() {  
        // slice - it works
        var s []int
        s = append(s,1)
        fmt.Println(s)
}
package main

func main() {  
        // map - it does not work
        var m map[string]int
        m["one"] = 1 //error
}

The compiler error is:

panic: assignment to entry in nil map

Map capacity

You can specify the map capacity when it’s created, but you can’t use the builtin cap function on maps.

package main

func main() {  
        m := make(map[string]int,10)
        cap(m) //error
}