iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Maps

A map in Go is a hash table — map[K]V. Lookup, insert, delete are O(1) average. Iteration order is randomised on purpose — do not rely on it.

Create, read, write, delete, idioms

EXAMPLE
package main

import (
    "fmt"
    "sort"
)

func main() {
    // 1) Create
    m := map[string]int{}                       // empty
    n := map[string]int{"a": 1, "b": 2}         // literal
    p := make(map[string]int, 100)               // hinted capacity

    // 2) Write
    m["score"] = 42

    // 3) Read — zero value if missing!
    v := m["missing"]    // 0 — silent surprise

    // Two-value read tells you if it's there
    if v, ok := m["score"]; ok {
        fmt.Println("found:", v)
    }

    // 4) Delete
    delete(m, "score")
    // delete on a missing key is a no-op (no panic)

    // 5) Length
    fmt.Println(len(n))

    // 6) Iterate — order is RANDOMISED
    for k, v := range n {
        fmt.Println(k, v)
    }

    // 7) Sort keys for deterministic iteration
    keys := make([]string, 0, len(n))
    for k := range n {
        keys = append(keys, k)
    }
    sort.Strings(keys)
    for _, k := range keys {
        fmt.Println(k, n[k])
    }

    // 8) Maps of slices — count-by
    wordCount := map[string]int{}
    for _, w := range []string{"go", "go", "rust", "go"} {
        wordCount[w]++
    }
    // map[go:3 rust:1]

    // 9) Set — use map[T]struct{}
    seen := map[string]struct{}{}
    seen["alice"] = struct{}{}
    seen["bob"]   = struct{}{}
    if _, ok := seen["alice"]; ok { /* ... */ }

    // 10) Nested maps — "group by"
    byCity := map[string][]User{}
    for _, u := range users {
        byCity[u.City] = append(byCity[u.City], u)
    }

    // 11) Map values are NOT addressable
    type Point struct{ X, Y int }
    pts := map[string]Point{"a": {1, 2}}
    // pts["a"].X = 9   // ERROR — cannot assign to struct field of map value
    pt := pts["a"]
    pt.X = 9
    pts["a"] = pt
    // Or use pointers if frequent updates:
    pp := map[string]*Point{"a": {1, 2}}
    pp["a"].X = 9       // OK

    // 12) Concurrent maps — built-in map is NOT goroutine-safe
    // Use sync.RWMutex or sync.Map
    var mu sync.RWMutex
    counts := map[string]int{}
    go func() {
        mu.Lock()
        counts["a"]++
        mu.Unlock()
    }()

    // sync.Map — for write-once, read-many workloads only
    var sm sync.Map
    sm.Store("a", 1)
    if v, ok := sm.Load("a"); ok { fmt.Println(v) }

    // 13) Initialise OR die
    var bad map[string]int       // nil map
    // bad["x"] = 1              // panic: assignment to entry in nil map
    bad = map[string]int{}
    bad["x"] = 1
}

Why it matters

Always use the two-value read for keys that may be absent — v, ok := m[k]. The single-value read returns the zero value, which silently hides “not found” bugs.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
ages := map[string]int{"Ada": 36}
ages["Bo"] = 28
if v, ok := ages["Ada"]; ok {
    fmt.Println(v)
}
delete(ages, "Bo")
Try it Yourself »

Exercise

Make an empty map of string to int.

m := (map[string]int)

Discussion

Loading…