Go

Why does m["k"].Field = 1 fail to compile for map[string]T where T is a struct?

Question 61MediumGo 1.22 to 1.25

Map elements are not addressable. m["k"] gives you a copy of the value, and assigning to a field of a temporary copy would do nothing. So the compiler rejects it: cannot assign to struct field m["k"].Field in map. The same rule blocks m[k][0] = x when the value is an array type. It also blocks calling pointer-receiver methods on the value: m[k].PtrMethod() fails with "cannot call pointer method PtrMethod on T", because the compiler cannot take the address of m[k].

type Point struct{ X, Y int }

m := map[string]Point{"a": {1, 2}}
// m["a"].X = 10            // compile error

// Fix 1: copy, modify, write back
p := m["a"]
p.X = 10
m["a"] = p

// Fix 2: store pointers
mp := map[string]*Point{"a": {1, 2}}
mp["a"].X = 10              // OK: modifies the pointee
// but beware: mp["missing"].X panics (nil pointer dereference)

// These DO work:
counts := map[string]int{}
counts["x"]++               // m[k] op= v is allowed (read-modify-write)
lists := map[string][]int{"a": {0}}
lists["a"][0] = 5           // OK: slice element is addressable via the header's pointer

Trade-off: map[K]*V allows in-place updates and avoids copying large values, but costs one allocation per value, adds GC scanning work, and lets callers who hold the pointer share mutable state. map[K]V is better for small value types.

More on Arrays, Slices, Maps & Strings

All 37 Arrays, Slices, Maps & Strings questions