Counting entries with len
The built-in len function returns the number of key-value pairs in a Go map:
scores := map[string]int{}
scores["Alice"] = 95
scores["Bob"] = 87
scores["Charlie"] = 72
n := len(scores)
fmt.Println(n) // 3
The same function gives the length of a string, a slice, an array and a channel. For a map, the length counts keys, not values, and each key counts once. If you assign to scores["Alice"] a second time, the map still has the same number of entries, because the key was overwritten.
How the length changes
- Assigning to a new key makes the length one bigger.
- Assigning to an existing key leaves it unchanged.
delete(scores, "Bob")makes it one smaller. Deleting a missing key changes nothing.- Reading a missing key does not add it, so lookups never change the length.
The length is cheap to get. Go keeps the count with the map, so len does not walk the entries.
Checking for an empty map
Compare the length with zero:
fmt.Println(len(scores) == 0) // false
empty := map[string]int{}
fmt.Println(len(empty)) // 0
A nil map also has length 0, so len(m) == 0 is a safe test for both an empty map and one that was never created. You can't tell them apart with len, but you can with m == nil.
Using the length
The length is an ordinary int, so it fits in conditions and arithmetic. Capture it before and after a change to see the effect:
before := len(scores)
scores["Carl"] = 61
fmt.Println(before, len(scores)) // 3 4
Keep in mind that len measures the container, not what is inside it. The length of a map of strings is the number of keys, not the number of characters. For a string, len counts bytes, so len("héy") is 4 because é takes two bytes in UTF-8, while len([]rune("héy")) is 3.
Length and iteration
Looping over a map with range runs exactly len(m) times when you don't change the map in the loop. That makes the length useful for sanity checks, or for sizing a slice before you copy the keys into it:
keys := make([]string, 0, len(scores))
for k := range scores {
keys = append(keys, k)
}
The slice starts empty but has room for every key, so the appends never need to allocate a bigger array. The order of the keys in the slice is unspecified, because map iteration order is.
Also note that the length says nothing about the values. A map whose values are all zero still has one entry per key, and its length is the same as before.
The exercise
The editor already holds the scores map with three students. The single step is to declare a variable named count with := and give it the number of entries, using len.
The solution in Go
scores := map[string]int{"Alice": 95, "Bob": 87, "Charlie": 72}
count := len(scores)
Here count is an int equal to 3. It is a snapshot taken at that moment, so if you add an entry later, count stays at 3 until you call len(scores) again.
Because the result is a plain int, you can pass it straight to fmt.Println, compare it, or store it, exactly as with any other number.
Common mistakes
- Using a method. Go has no
scores.len()orscores.length. Length is a built-in function that takes the map as its argument. - Expecting
cap. Slices have a capacity, butcapdoesn't accept a map, and the program doesn't compile. - Declaring and not using. Go rejects a variable that is never used. In a full program,
counthas to be printed or used somewhere. - Counting with a loop for no reason. A
rangeloop with a counter gives the same number, butlenis shorter and faster.
Key takeaways
len(m)is the number of keys in the map.- Overwriting a key doesn't change the length, and adding or deleting one does.
len(m) == 0checks for an empty map, and also works on a nil map.