Sometimes we do not need data to be independent. Usually data is associated with a specific object, like a person’s salary or user’s profile. In such situation, we still use array indices to track each object, but that becomes very difficult. This is where Maps become useful. Maps are just a key-value association.
Overview
Map is unordered collection of key-value pairs. They are usually associated with key. So, they are called associative arrays or dictionary in other languages. They are implemented using hash tables and due to that they provide constant time lookup. So, add, get and delete operations are very fast with maps.
Creating Maps in Golang
The general syntax for creation of a map looks like this.
1var <name> map[<key_data_type>]<value_data_type>
Example of map Declaration:
1var employees map[string]int
If we try to assign key-value pairs to uninitialized map, we get an error.
Example:
1package main
2
3import "fmt"
4
5func main() {
6 var employees map[string]int
7 employees["Akshay"] = 90000 // throws error
8 fmt.Println(employees)
9}
To create a map with key-value pairs we also have to initialize it with key-value pairs. In above code, we declared an empty map, this assigns a value nil to employees map. Although we can print empty map, we cannot assign a key to this map. If we actually want to create empty map, we have to use make function.
Example:
1package main
2
3import "fmt"
4
5func main() {
6 numbers := map[string]int{"one": 1, "two": 2}
7 fmt.Println(numbers)
8}
Output:
map[one:1 two:2]
We can find how many key value pairs exist in a map using len function.
Example:
1package main
2
3import "fmt"
4
5func main() {
6 numbers := map[string]int{"one": 1, "two": 2}
7 fmt.Println(len(numbers)) // 2
8}
We can also declare and initialize a map with make function. We can also assign new key-value pairs using assignment operator as shown in line 9 below. This is how we can create empty map and still be able to assign key-value pairs later.
1package main
2
3import "fmt"
4
5func main() {
6 numbers := make(map[string]int)
7 fmt.Println(numbers)
8 fmt.Println(len(numbers))
9 numbers["one"] = 1 // now we can assign key-value
10 fmt.Println(numbers)
11}
Output:
map[]
0
map[one:1]
We cannot assign duplicate keys while initializing a map.
1package main
2
3import "fmt"
4
5func main() {
6 m := map[string]int{
7 "one": 1,
8 "two": 2,
9 "three": 3,
10 "one": 100,
11 } // duplicate key "one" in map literal
12 fmt.Println(m)
13}
Accessing elements of a Map in Go
We can get values for a specific key using its keys. Just like arrays and slices we can use [] to access value associated with a key.
Example:
1package main
2
3import "fmt"
4
5func main() {
6 numbers := map[string]int{"one": 1, "two": 2, "three": 3}
7 fmt.Println(numbers["one"])
8}
Output:
1
If we try to access a key which doesn’t exist in the map, we get zero value for that specific data type.
1package main
2
3import "fmt"
4
5func main() {
6 m := map[string]int{
7 "one": 1,
8 "two": 2,
9 "three": 3,
10 }
11 fmt.Println(m["ten"]) // 0
12}
To avoid getting incorrect zero value, we should always make sure to check if the key exists in the map. When getting values, we get value and a boolean flag if the key exists or not. If key doesn’t exist, the first value will be zero value. This we can use with conditionals to verify if a key exists and if exists, get the value else do something else.
1package main
2
3import "fmt"
4
5func main() {
6 numbers := map[string]int{"one": 1, "two": 2, "three": 3}
7 value, found := numbers["three"]
8 fmt.Println(found, value)
9
10 value, found = numbers["four"]
11 fmt.Println(found, value)
12
13 value, found = numbers["ten"]
14 if found {
15 fmt.Println("Value for numbers['ten']", value)
16 } else {
17 fmt.Println("Key 'ten' does not exist.")
18 }
19}
Output:
true 3
false 0
Key 'ten' does not exist.
We can assign new key-value pairs using map_name[key] = value syntax as you’ve already seen. However, if we try to assign the existing key with a new value, it will simply overwrite existing values.
1package main
2
3import "fmt"
4
5func main() {
6 numbers := map[string]int{"one": 1, "two": 2, "three": 3}
7 fmt.Println(numbers)
8 numbers["one"] = 11
9 fmt.Println(numbers)
10}
In above code, line 8 reassigns the key one with new value 11 which can be seen from the below output.
**Output:
map[one:1 three:3 two:2]
map[one:11 three:3 two:2]
Create a Map from an Array
Sometimes, it may be useful to create a map from an existing array, below code shows an example of this. In this case, we are using array indices as map keys. Also, note that additional keys will get zero value for specific data type as their value, for example, keys 4 and 5.
Example:
1package main
2
3import "fmt"
4
5func main() {
6 arr := [5]string{"hi", "hello", "there"}
7 greetings := make(map[int]string, 5)
8 for index, elem := range arr {
9 greetings[index+1] = elem
10 }
11 fmt.Println(greetings)
12}
Iterating through Maps in Go
For looping through each key-value pair in a map, we can use range to get both key and value of each pairs.
Example:
1package main
2
3import "fmt"
4
5func main() {
6 numbers := map[string]int{"one": 1, "two": 2, "three": 3}
7 for key, value := range numbers {
8 fmt.Println(key, "has value", value)
9 }
10}
Again, the map data-structure is unordered. So, output below sometimes may not match exactly.
Output:
one has value 1
two has value 2
three has value 3
Clean up Map
For clearing any key-value pair from a map, we can use built-in function delete.
1package main
2
3import "fmt"
4
5func main() {
6 numbers := map[string]int{"one": 1, "two": 2, "three": 3}
7 fmt.Printf("%v\n", numbers)
8 for key, _ := range numbers {
9 delete(numbers, key)
10 }
11 fmt.Printf("%v\n", numbers)
12}
Output:
map[one:1 three:3 two:2]
map[]
Conclusion
In this lesson, we looked at various operations we can perform on Map data structure in Go. These are basically associative arrays with key-value pairs. We learned how to create a map, get element for a specific key, add new key-value pairs. We also learned how we can iterate over a map or delete map from memory.


Comments