Map operations: comma-ok and delete

"Missing key" and "present with the zero value" look identical through a plain lookup. That works for some patterns (counting word frequencies, accumulating into a running total), but it breaks down the moment the zero value is a legitimate stored value: a map of shopping-cart quantities where 0 means "explicitly cleared", a map of feature flags where false means "explicitly turned off". This lesson covers the two operations that handle "missing versus present" cleanly: the comma-ok form for reading, and delete for removal.

Comma-ok: telling missing from zero

Map reads have two forms. The single-value form you have seen returns only the value:

ages := map[string]int{"alice": 30}

fmt.Println(ages["alice"])    // 30
fmt.Println(ages["nobody"])   // 0   (can't tell: really 0, or missing?)

The comma-ok form adds a second return value: a bool that is true if the key was present and false if it was not:

ages := map[string]int{"alice": 30, "charlie": 0}

if v, ok := ages["alice"]; ok {
    fmt.Println("alice is", v)
} else {
    fmt.Println("no alice")
}

if v, ok := ages["charlie"]; ok {
    fmt.Println("charlie is", v)
} else {
    fmt.Println("no charlie")
}

if v, ok := ages["nobody"]; ok {
    fmt.Println("nobody is", v)
} else {
    fmt.Println("no nobody")
}

Output:

alice is 30
charlie is 0
no nobody

charlie exists with value 0; nobody does not exist at all. Without ok, both reads would give you 0 and you could not tell them apart. With ok, you always can.

The short-statement if form from Chapter 2 (if v, ok := m[k]; ok { ... }) is the pattern this feature exists for. You will write it dozens of times in real Go code.

delete removes a key

delete(m, k) removes the entry for key k from map m. It returns nothing. Deleting a key that is not present is a no-op, not an error:

m := map[string]int{"a": 1, "b": 2, "c": 3}

delete(m, "b")
fmt.Println(m)          // map[a:1 c:3]

delete(m, "nobody")     // no-op, no error
fmt.Println(m)          // map[a:1 c:3]

After delete, reading the deleted key returns the zero value (just like any other missing key), and a comma-ok read returns false for the ok result.

len counts the entries

len(m) returns the number of key-value pairs in the map:

m := map[string]int{"a": 1, "b": 2}
fmt.Println(len(m))   // 2

m["c"] = 3
fmt.Println(len(m))   // 3

delete(m, "a")
fmt.Println(len(m))   // 2

len(nil) on a map is 0, so if len(m) == 0 { ... } works whether the map is nil or merely empty, without any special-case branch.

Task

Starter declares inventory := map[string]int{"apple": 3, "banana": 0, "cherry": 12}. The "banana" entry is legitimately zero (we have zero bananas in stock), not missing.

  • Use the comma-ok form to look up inventory["banana"]. If the key is present, print "banana in stock: <count>". If not, print "banana not tracked".
  • Use the comma-ok form again for inventory["durian"]. Print "durian in stock: <count>" if present, "durian not tracked" if not.
  • Delete "apple" from the map.
  • Print len(inventory) on its own line.

Expected output:

banana in stock: 0
durian not tracked
2
Expected output
banana in stock: 0
durian not tracked
2