Skip to content
Lesson 11 of 14

Step 1 of 5 · Reading · ~4 min

Learn

Collections

Maps

A map stores key/value pairs and finds a value by its key in roughly constant time, however many pairs it holds. By the end of this lesson you can build one, read it without tripping over missing keys, tally occurrences with it, and print its contents in a stable order.

Creating, writing, reading

go

Key types must be comparable: strings, numbers, bools. Value types can be anything.

One landmine first: a map that is declared but never built is nil. var m map[string]int reads fine and panics on the first write with assignment to entry in nil map. Build every map with make or a literal and you will never meet it.

Reading a key that is not there

That is never an error. You get the value type's zero value: 0 for an int map, "" for a string map, false for a bool map.

go

Convenient, but it hides one thing: a stored 0 and an absent key look identical. The two-value form, called comma-ok, separates them:

go

Use comma-ok when absence itself means something, and the plain read when zero is a fine default.

Tallying with the zero value

Because a missing key reads as zero, you can add to a counter that does not exist yet. Counting the colors in a slice is one statement inside the loop:

go

Five items went in and len(tally) is 3, because three keys were used. When the values carry no information, a map is Go's set: seen := map[string]bool{}, then seen[name] = true. A key can only be stored once, so the map's length tells you how many different names went in, no matter how often each one was written.

Iteration has no order

go

Ranging over a map visits every pair exactly once, in an order Go deliberately randomizes on every run -- three runs, three orders, so nobody can write code that depends on it. When output must be stable, pull the keys out, sort them, and look each one up:

go

Counting how many entries satisfy some condition needs no sorting -- order cannot change a count -- but printing them does.

Common mistakes

  • Reporting items instead of keys. For the line red red red a program that says three colors is printing how many items it read, not the map's length. A map with one key has length 1 however often that key was written.
  • Treating every key as a one-timer. For red red blue the map has 2 keys, but only one of them was stored a single time. The number of keys and the number of keys whose value is 1 are different numbers, and the second one costs a pass over the values.
  • Assuming at least one entry exists. An empty input line yields an empty slice and an empty map: both lengths are 0, and no loop body runs. Reaching for words[0] to "get started" panics there with index out of range.
  • Expecting keys to be case-insensitive. Keys are compared exactly, so Go and go are two separate entries. Lower-case the text first if you want them merged.

Your exercise

Tally the words of one input line in a map, then report two numbers: how many different words appeared, and how many appeared exactly once. The starter already splits the line into words and creates the empty map counts, and prints two zeros so you can see the shape. The second number is the trap -- it is not the size of the map.

Up nextStructsCollections

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…