In this tutorial, we are going to look at maps in Golang, how to create them, add entries to a map, iterate map and delete from a map.

What is a map
A map is a collection of elements which are grouped in key-value pairs. Each key refers to a single value.
Maps provide faster access and iteration and that is why they commonly used to store data. A map may be visualized as below.
Maps representation in Golang
Keys of a map should be of same data type and values of a map should be of same data type. Keys and values may be of different data types.
Data type of keys should be such that they can be compared using == or != operators.
Thus, integers, decimal numbers, strings, pointers, interfaces, arrays and structs can be used as keys while functions, map or slices cannot be used as keys.
Create map
There are two ways to create a map.
1. Using map literal
A map can be created using below syntax

<variable name> := map[key type]value type {
key1: value1,
key2: value2,
}

where,
variable name is the name of variable with which the map will be accessed.
map is the Golang literal to create a map. It is followed by square brackets containing the type of keys this map will contain and type of values outside the square brackets.
Map entries or KeyValue pairs are given inside curly braces.

Each Key and Value are separated by a colon while KeyValue pairs are separated by a comma.
Remember that the last KeyValue pair should also end with a comma else there will be a compiler error.
Creating empty map
Below syntax creates an empty map with map literal syntax. Keys of this map are of type int while values are string.

m := map[int]string{}

If you do not write curly braces after the declaration, you will get an error
type map[int]string is not an expression

2. Using make() function
Builtin make() function can also be used to create a map. It takes the map literal as argument.
Syntax is

m := make(map[int]string)

This creates an empty map whose keys are of type int and values are of type string.

There is another version of make() which also takes the initial size of map as the second argument.

m := make(map[int]string, 10)

This does not mean that this map can contain only 10 entries. Map can expand its size dynamically when more entries are added.

Remember that when a map is created with make(), it does not any initial key-value pairs but with map literal, you can provide default key-value pairs and also add entries later.
Append to map
For adding key-value pairs to a map, below syntax is used

m[key] = value

Data types of key and value should be same as that given while creating a map.

Remember that you can only add entries to an initialized map. If a map is simply declared using var keyword, then it is nil and you cannot add values to a nil map.
Thus below code will raise an error.

var m map[string]string
m["1"]="A"

as below

panic: assignment to entry in nil map

To resolve this, first check before adding an entry

var m map[string]string
if m != nil {
  m["1"]="A"
} else {
  fmt.Println("Map is not initialized")
}

Map example
Following code initializes a map using map literal and then adds an entry into it.

package main

import "fmt"

func main() {
  // create a map
  m := map[int]string {
     1:"A",
     2:"B",
  }
  // add entry to map
  m[3]="C"
  fmt.Println("Map is", m)
}

When the map is printed, it gives

Map is map[1:A 2:B 3:C]

Notice that it contains all the key-value pairs.

Below code example creates a map with make() function and then adds all the three entries.

package main

import "fmt"

func main() {
   // create a map
   m := make(map[int]string)
   m[1]="A"
   m[2]="B"
   m[3]="C"
  fmt.Println("Map is", m)
}

Access values
In order to get a value associated with a key, use map variable followed by the name of key enclosed in square brackets.
Syntax is

map-variable[key-name]

This returns the value linked to the given key.
If the key is not present in the map, then it returns the zero value for the corresponding data type of the value.
Example

package main

import "fmt"

func main() {
   // create a map
   m := make(map[int]int)
   // assign key-values
   m[1] = 10
   m[2] = 20
   m[3] = 30
   fmt.Println("Value for key 1 is", m[1])
   fmt.Println("Value for key 2 is", m[2])
   fmt.Println("Value for key 3 is", m[3])
   // access non-existing key 
   fmt.Println("Value for key 4 is", m[4])
}

This prints

Value for key 1 is 10
Value for key 2 is 20
Value for key 3 is 30
Value for key 4 is 0

Look, for a key that does not exist, it prints 0, which is the zero value for int data type.

Iterating a map
Iterating a map means looping over its entries. A map can be iterated using a for loop with range clause.
Syntax is

for key, value := range map {

}

where key and value are variable names that contain the key and value of a map in every iteration. Example,

package main

import "fmt"

func main() {
  // create a map
  m := make(map[int]int)
  m[1] = 10
  m[2] = 20
  m[3] = 30
  for k, v := range m {
    fmt.Println("Key is:",k, ", Value is:",v)
  }
}

This prints

Key is: 1 , Value is: 10
Key is: 2 , Value is: 20
Key is: 3 , Value is: 30

If you need only the key, then drop the second variable from for loop as below

// only key is required
for k:= range m {
  fmt.Println("Key is:",k)
}

If you need only the value, then replace the key variable with a blank identifier otherwise, you will have to use this variable to prevent a compiler error.

// key not required
for _, v := range m {
  fmt.Println("Value is:",v)
}

Delete Entry
For removing a key-value pair from map, use delete() function passing it the map variable and the key of the entry to be deleted as

delete(m, key)

Example,

package main

import "fmt"

func main() {
  // create a map
  m := make(map[int]int)
  m[1] = 10
  m[2] = 20
  m[3] = 30
  fmt.Println("Original map:",m)
  delete(m,2)
  fmt.Println("Map after deletion:",m)
}

which prints

Original map: map[1:10 2:20 3:30] Map after deletion: map[1:10 3:30]

If a non-existing key is provided as argument to delete(), nothing happens. Thus,

// no effect
delete(m, 5)

Check for key presence
Since Golang does not give any error on missing key and it returns a value(the zero value) even if a key is not present, you need to have some way of checking for key presence.
You can test if a key is present in the map or not using the same syntax as for accessing a key

map[key]

Assign this to two comma separated variables, out of which first one contains the value and second is a bool which is true if the key is present and false if it is not as shown in the following example

// create a map
m := map[string]string{
   "ram":"2GB",
   "hdd":"350GB",
}
// declare variables
var value string
var ok bool
// access key
value, ok = m["camera"]

In this case, ok will be false and value will be empty string.
You can check for key presence and then take a relevant action using if-else blocks as below

if ok {
   fmt.Println("Value is",value)
} else {
   fmt.Println("Key not present")
}

In Golang, this is called comma ok idiom.
It is not necessary to name the bool variable as ok, it can be any user defined name.

Variable declarations in this example can be shortened by using := operator as

// create a map
m := map[string]string{
   "ram":"2GB",
   "hdd":"350GB",
}
// access key
value, ok := m["camera"]

Hope the article was useful.