Go - Maps

Intro

Maps are somewhat similar to what other languages call “dictionaries” or “hashes”. A map maps keys to values.

Here are some points to look at:

  • Maps allows us to quickly access to an element/value using a unique key.
  • Map keys must be unique because otherwise it can’t find the corresponding values/elements.
  • The types of Map Keys and Values in Maps can be different.
  • A Map Key must be a comparable type. You can read more about comparing on the Golang spec: comparing.
  • All Map Keys and Map Values must belong to their corresponding types. They can't be mixed up.
  • A Map Variable (or a Value) is nothing but a pointer to a Map Header Value in the memory.
  • A Map Value only contains the memory address of a Map Header.

Creating Maps

Maps can be created in two ways:

1) Using map literals

package main

import "fmt"

func main (){
    m := map[string]string{ //here we are declaring the key to be of type string and the value to be of type string
        "Picard":"The next generation",
        "Janeway":"Voyager",
        "Kirk":"Star Trek",
    }
    fmt.Println(m)
}

playground

Again this is very similar to object creation in javascript. Remove the types and it is exactly the same.

Maps can contain any valid type. When using a custom type in a map, you can omit the type name in a map literal definition:

package main

import "fmt"

type Location struct {
    Lat, Lng float64
}

func main() {
    m := map[string]Location{
    "Bell Labs": {40.68433, -74.39967},
    "Google": {37.42202, -122.08408},
    }

    fmt.Println(m)
}

playground

2) With the make keyword

The make built-in function allocates and initializes an object of type slice, map, or chan (only).

package main

import "fmt"

func main (){
    m := make(map[string]string,3) // The second argument here is the initial size of the map (optional).
    m["Picard"] = "The next generation"
    m["Janeway"] = "Voyager"
    m["Kirk"] = "Star Trek"
    fmt.Println(m)
}

playground

The only reason to use the make key word is if you want to decide the size of the map before hand.

Lets go through some common actions with maps.

Playing with Map

Adding values

m[key] = elem

Checking if a key exists in a map

elem, ok = m[key]
if ok { // key is in map
  do something with elem
}

Retrieve an element

elem = m[key]

Delete an element

delete(m, key)

Get length of map

length = len(m)

Iterating through a map

for key,val := range m{ //notice the range key word we will talk more about this
    fmt.Printf("map has key %s and value %s \n",key,val)
}

Example - Retreive values from map

package main

import "fmt"

func main (){
    m := map[string]string{
        "Picard":"The next generation",
        "Janeway":"Voyager",
        "Kirk":"Star Trek",
    }
    if v,ok := m["Picard"]; ok{ // in this case ok is a bool that will be true if the key exists.
        fmt.Println(v)
    }
    if v := m["Picard"]; v != ""{ // in this case you have to assert something about the returned value. I prefer the example above.
        fmt.Println(v)
    }
    if _,ok := m["not here"]; !ok{ //notice the _ here this is used to ignore a return value
           fmt.Println("no key with that name")
    }
}

playground

Example - Iterating through a map

package main

import "fmt"

func main (){
    m := map[string]string{
        "Picard":"The next generation",
        "Janeway":"Voyager",
        "Kirk":"Star Trek",
    }
    for key,val := range m{ //notice the range key word we will talk more about this
        fmt.Printf("map has key %s and value %s \n",key,val)
    }
}

playground

Range So we saw the range keyword above. A range clause provides a way to iterate over an array, slice, string, map, or channel (more on channels in the future). It is only used in conjunction with a for loop. One thing to note is that when you use the range key word, for each loop, it copies the current key and value into the vars. This means that if you change the value in the loop it will not be reflected in the map or slice.

Example - Get the size of a map

To find out the size of a map (i.e the number of keys it has) we use the builtin len function.

package main

import "fmt"

func main (){
    m := map[string]string{
        "Picard":"The next generation",
        "Janeway":"Voyager",
        "Kirk":"Star Trek",
    }
    fmt.Println(len(m)) //outputs 3
}

playground

Example - Deleting items from a map

To Delete an item from a map use the buit in delete function:

package main

import "fmt"

func main (){
    m := map[string]string{
        "Picard":"The next generation",
        "Janeway":"Voyager",
        "Kirk":"Star Trek",
    }
    delete(m,"Picard") //delete takes the map as the first arg and the key as the second
    fmt.Println(m)
}

playground


See also