Go

Why doesn't m["k"].Inc() compile when Inc has a pointer receiver? What other values are not addressable?

Question 82HardGo 1.22 to 1.25
type Counter struct{ n int }
func (c *Counter) Inc() { c.n++ }

m := map[string]Counter{"k": {}}
// m["k"].Inc()   // error: cannot call pointer method Inc on Counter
// m["k"].n = 5   // error: cannot assign to struct field m["k"].n in map
// Counter{}.Inc() // error: cannot call pointer method Inc on Counter

// Fix 1: store pointers
mp := map[string]*Counter{"k": {}}
mp["k"].Inc()

// Fix 2: read, modify, write back
c := m["k"]
c.Inc()
m["k"] = c

Map elements are not addressable. Growing the map moves entries (bucket evacuation in the classic implementation, table splits and rehashing in the Swiss-table maps used since Go 1.24), so a pointer to an element could be left dangling. Without an address, the compiler cannot build &m["k"] for the pointer receiver.

Other non-addressable operands include composite literals used directly (but &T{} is allowed as special syntax), function return values, constants, string bytes, values inside interfaces, and the result of a type assertion. Addressable operands include variables, pointer dereferences, slice elements (s[i].Inc() works), and fields of addressable structs.

More on Interfaces, Methods & Embedding

All 35 Interfaces, Methods & Embedding questions