Skip to content
Theory · Maps · lesson 2 of 9

Is the key there

In the previous lesson we found out that when a name is not in the phone book, a map answers with the zero value. That is usually handy, but sometimes it gets in the way. In a map of player scores, the value 0 can be a real result. A plain read cannot tell it apart from a key that is not there:

GO
package main

import "fmt"

func main() {
    scores := map[string]int{"ann": 0, "bob": 7}
    fmt.Println(scores["ann"], scores["max"]) // 0 0
}

Here are two different cases:

  • the player ann played and scored zero points;
  • the player max is not in the map at all.

Both reads return 0, because a missing key reads as the zero value. It is like asking a phone book for a number and hearing "0": you cannot tell whether that is the number or the person is not in the book.

Two values from a read

A read from a map can return a second value of type bool. It is true if the key is there and false if it is not. This form is called the comma ok idiom, after the comma between the two variables:

GO
scores := map[string]int{"ann": 0, "bob": 7}
v, ok := scores["ann"]
fmt.Println(v, ok) // 0 true
w, found := scores["max"]
fmt.Println(w, found) // 0 false

Let's walk through the example line by line:

  1. v, ok := scores["ann"] reads two values. The key "ann" is there, so ok is true, though v is 0: what counts is the key, not its value.
  2. fmt.Println(v, ok) prints 0 true.
  3. w, found := scores["max"] reads a missing key. The first value is the zero value, as with a plain read, and the second is false.
  4. fmt.Println(w, found) prints 0 false.

The second variable can have any name: ok is a convention, not a keyword. If the value itself is not needed, write _ in place of the first variable: _, ok := scores["max"].

Interviewers like to ask: "How do you check whether a key is in a map?" The answer is to read two values and look at the second.

When comma ok is needed

The choice depends on whether the zero value can be a real one:

  • it can—zero points, an empty name, false in a map[string]bool—so you need comma ok;
  • it cannot—for example, a price is always above zero—so a plain read and a zero check are enough.

A check in if

Most often, comma ok sits in the init statement of an if. The variables v and ok are then visible only inside the if and stay out of the rest of the code:

GO
scores := map[string]int{"bob": 7}
if v, ok := scores["bob"]; ok {
    fmt.Println("bob:", v) // bob: 7
}
if _, ok := scores["max"]; !ok {
    fmt.Println("no max") // no max
}

Let's walk through both ifs:

  1. The key "bob" is there, so the first if prints his score: bob: 7.
  2. The key "max" is not, ok is false, and the second if prints no max.

A map as a set

Sometimes the zero value of a missing key is exactly what helps. That is how a set works: a collection of values without repeats. Go has no separate set type, and interviewers often ask how to make one. The answer is a map with bool values: seen := map[string]bool{}.

You work with such a set like this:

  • you add a value with seen[w] = true;
  • you check it with a plain read: if seen[w];
  • nobody writes false into such a map, so false on a read means one thing: the key is not in the set.

Comma ok is not needed here. This makes it handy to filter out repeats: if seen[w] is already true, the value came up before.

Common mistake

The presence of a key is checked by comparing with zero:

GO
scores := map[string]int{"ann": 0}
if scores["ann"] == 0 { // ✗
    fmt.Println("no ann")
}

The program prints no ann, though "ann" is in the map: its value 0 equals a missing key's zero value. This check mixes up a player with zero points and a player who is not there. Check the second value instead: if _, ok := scores["ann"]; !ok.

Key points

  • v, ok := m[k] returns the value and true if the key is there, or the zero value and false if it is not.
  • Comma ok is needed when the zero value can be a real one, like zero points.
  • A set in Go is a map[T]bool: add with seen[x] = true, check with if seen[x].

Subscribe to take the course

The course is free. Sign in with Telegram and subscribe to the channel to open every lesson.

Sign in another way