Go Maps
Creating Maps
make, literal, and nil maps
// Create with make
m := make(map[string]int)
m["alice"] = 42
m["bob"] = 17
// Literal
scores := map[string]int{
"alice": 42,
"bob": 17,
}
// nil map — reads work, writes panic
var empty map[string]int
fmt.Println(empty["x"]) // 0 (zero value, no panic)
// empty["x"] = 1 // PANIC: assignment to entry in nil map
Always make or use a literal before writing to a map. Reading from a nil or missing key returns the zero value of the value type.
The Comma-Ok Idiom
Distinguish "key absent" from "value is zero"
m := map[string]int{"alice": 0, "bob": 17}
val, ok := m["alice"]
fmt.Println(val, ok) // 0 true
val, ok = m["carol"]
fmt.Println(val, ok) // 0 false
if v, ok := m["bob"]; ok {
fmt.Printf("bob: %d\n", v)
}
Without the second return value, you cannot tell whether a key exists with value 0 or is missing entirely.
Delete & Iterate
delete removes a key; range iterates
m := map[string]int{"a": 1, "b": 2, "c": 3}
delete(m, "b") // no-op if key missing
// Iteration order is random
for k, v := range m {
fmt.Printf("%s: %d\n", k, v)
}
// Sorted iteration — extract keys first
keys := make([]string, 0, len(m))
for k := range m {
keys = append(keys, k)
}
sort.Strings(keys)
for _, k := range keys {
fmt.Printf("%s: %d\n", k, m[k])
}
Map iteration order is deliberately randomized by the Go runtime. If you need deterministic output, sort the keys.
Patterns
Word frequency counter
func wordFreq(text string) map[string]int {
freq := make(map[string]int)
for _, word := range strings.Fields(text) {
freq[word]++ // zero value of int is 0
}
return freq
}
Set using map[T]struct{}
type Set map[string]struct{}
func (s Set) Add(item string) { s[item] = struct{}{} }
func (s Set) Has(item string) bool { _, ok := s[item]; return ok }
func (s Set) Remove(item string) { delete(s, item) }
seen := make(Set)
seen.Add("10.50.1.1")
if seen.Has("10.50.1.1") {
fmt.Println("already seen")
}
struct{} consumes zero bytes. map[T]struct{} is the idiomatic Go set — more memory-efficient than map[T]bool.
Group by — map of slices
type Host struct {
Name string
VLAN int
}
func groupByVLAN(hosts []Host) map[int][]Host {
groups := make(map[int][]Host)
for _, h := range hosts {
groups[h.VLAN] = append(groups[h.VLAN], h)
}
return groups
}
append on a nil slice works correctly, so there is no need to check whether the key exists before appending.