Go by Example

Maps

Key-value stores with make, literals, get/set/delete, the comma-ok idiom, and range iteration.

A map is Go's built-in hash table. Keys must be comparable (== must work on the type); values can be any type. Reading a missing key always returns the zero value - use the comma-ok idiom to distinguish "key is absent" from "value is zero".

Create a map with make or a map literal. Set, get, and delete entries with simple syntax.

package main
 
import "fmt"
 
func main() {
    // Map literal
    ages := map[string]int{
        "Alice": 30,
        "Bob":   25,
    }
 
    // Set
    ages["Carol"] = 28
 
    // Get
    fmt.Println(ages["Alice"]) // 30
 
    // Delete
    delete(ages, "Bob")
    fmt.Println(len(ages)) // 2
}

Reading a missing key returns the zero value of the value type - 0 for integers, "" for strings. The comma-ok idiom distinguishes "key is absent" from "value happens to be zero".

package main
 
import "fmt"
 
func main() {
    scores := map[string]int{"Alice": 0}
 
    // Both return 0 - how do you tell them apart?
    a := scores["Alice"]   // 0 (present, value is zero)
    b := scores["Bob"]     // 0 (absent)
    fmt.Println(a, b)      // 0 0
 
    // Comma-ok tells you definitively
    v, ok := scores["Alice"]
    fmt.Println(v, ok) // 0 true
 
    v, ok = scores["Bob"]
    fmt.Println(v, ok) // 0 false
}

range iterates over a map's key-value pairs. Iteration order is randomised on every run - do not rely on it.

package main
 
import "fmt"
 
func main() {
    capitals := map[string]string{
        "France":  "Paris",
        "Japan":   "Tokyo",
        "Brazil":  "Brasília",
    }
 
    for country, city := range capitals {
        fmt.Printf("%s → %s\n", country, city)
    }
    // Order varies every run
}

In production

Maps are not safe for concurrent reads-and-writes. A goroutine writing while another reads causes a data race and a runtime panic (Go detects this since 1.6). Use sync.RWMutex to protect maps you share across goroutines, or use sync.Map for mostly-read workloads. Reading a missing key silently returns the zero value - a common footgun when the zero value is valid (e.g., map[string]int counting occurrences: m["missing"] returns 0, which looks like a valid count). Always check with the comma-ok idiom before acting on the result.

Enjoyed this? Get more essays on software craft delivered to your inbox.

Subscribe free