Learning Go - Maps

Background

In Go, we are provided with in-build HashTables or HashMap to store associated data. A map in Go is similar to Python’s dictionary and the object of JavaScript. HashMaps are very useful because:

  • It supports mapping of a data type to another data type.
  • Getting values of a key is mostly a constant time operation.

Maps

The Go map is an associative container. We will explore how to create, read, update and delete a map and the related key values of it.

Creating a Map

The syntax to declare a map is like map[key_type]value_type. When we declare a map, it’s actually nil and hence we need to initialize it using the make() function. We have already used it for slices (however slices doesn’t need separate initialization by calling make() but for map it is required).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main 

import "fmt"

func main() {
// declare
var grades map[string]int

// initialize
grades = make(map[string]int)

// add values
grades["Tom"] = 90
grades["Jerry"] = 95

// print
fmt.Println(grades)
}

The output of the above code will be map[Jerry:95 Tom:90].

In the above code, we have declared a variable grades to store the integer grades of random students like “Tom” and “Jerry”. Before adding the values, it was required to initialize the map using make(). The key for the map is string i.e. names of the students and the value is int i.e. grades value for each student.

1
2
// we can also allocate default capacity for the map
grades := make(map[string]int, 100) // <-- store 100 students

We can use the second argument of the make() function to allocate default capacity to the map. Also we can skip the call to make() if we can initialize the map when declaring like:

1
2
3
4
5
// skip make(), declare and initialize directly 
grades := map[string]int{
"Tom": 90,
"Jerry": 95,
}

Reading Values

The map allows us to read if a key with the value is present in the map or not. let’s see how we read the values:

1
2
3
4
5
6
val, ok := grades["Ashok"] 
if !ok {
fmt.Println("no key found")
} else {
fmt.Printf("Grades of Ashok = %d\n", val)
}

We use the val, ok idiom to check if key is present in a map. If the key is present then the value will can be access using the val variable. Note that we need to conditionally verify the ok variable which is a boolean and is used to indicate the presence of the key we are trying to get.

We can also use the for loop with range on the map to read the values. Let’s see an example:

1
2
3
for key, value := range grades {
fmt.Printf("Grade of %s is %d\n", key, value)
}

Updating Values

We can use the assignment operator to update a value for a key of the map. This is pretty simple to do.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import "fmt"

func main() {

fruits := map[string]int{
"apple": 10,
"banana": 20,
"cherry": 30,
}

fmt.Println("before:", fruits)

// update a key
fruits["apple"] = 100

fmt.Println("after:", fruits)
}

Deleting Keys

In Go, deleting keys from a map is done using the delete function. This function allows you to remove a key-value pair from the map. Let’s look at an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main

import "fmt"

func main() {

fruits := map[string]int{
"apple": 10,
"banana": 20,
"cherry": 30,
}

fmt.Println("before delete:", fruits)

// delete a key
delete(fruits, "banana")

fmt.Println("after delete:", fruits)
}

Deleting a Map

We do not have any dedicated method for deleting the map. What we can do to delete a map is that we can set it to nil. For the above example, we can do something like: fruits = nil. A nil map is essentially a map that has no underlying data structure. Calling delete on a nil map has no effect i.e. it won’t panic or do anything.

Outro

I hope you enjoyed reading this, stay tuned for the next topic - Structs in Go.