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
- Q80Why does this function return a non-nil error even when nothing failed? How do you fix it?
- Q81Explain method sets. Why does
*Tsatisfy an interface whenTdoes not? - Q83How do you decide between value and pointer receivers?
- Q84Compare
v := x.(T)withv, ok := x.(T). What happens whenTis an interface type? - Q85Explain type switch semantics. What does this print?
- Q86Is struct embedding inheritance? How does method promotion work?