What is addressability, and why can't you call a pointer method on a map element?
An expression is addressable if you can take its address with &. That includes variables, pointer dereferences, slice elements, and fields or elements of addressable structs and arrays. These are not addressable:
- map elements
- function return values
- constants and literals (except that
&T{}is allowed as special syntax) - results of a type assertion
- string bytes
type Counter struct{ n int }
func (c *Counter) Inc() { c.n++ }
m := map[string]Counter{"a": {}}
// m["a"].Inc() // compile error: cannot call pointer method Inc on Counter
// m["a"].n = 5 // compile error: cannot assign to struct field m["a"].n in map
c := m["a"]; c.Inc(); m["a"] = c // copy, change, write back
mp := map[string]*Counter{"a": {}}
mp["a"].Inc() // OK: the element is a pointer
s := []Counter{{}}
s[0].Inc() // OK: slice elements are addressable
// Counter{}.Inc() // compile error: a composite literal value is not addressable
(&Counter{}).Inc() // OK
// newCounter().Inc() // compile error if newCounter returns Counter (not *Counter)
Why map elements can't be addressed: when a map grows, the runtime moves its entries to new memory. This is true of both the old bucket-based map and the Swiss-table map that has been the default since Go 1.24, where tables split and rehash as they grow. A pointer to an entry would be left pointing at stale memory, or at a slot that now holds a different key. Slices don't have this problem. A pointer to a slice element always points into a live backing array. After an append that reallocates, the old pointer still refers to the old array, which the GC keeps alive.
More on Language Fundamentals & Types
- Q27What does the
comparableconstraint mean in generics, and what changed in Go 1.20? - Q28Explain method sets. Why does
var s Speaker = Dog{}fail to compile? - Q30How does struct embedding affect method sets and name resolution?
- Q31Why is an interface holding a nil pointer not equal to nil? What does this print?
- Q32What is the difference between a defined type (
type A B) and an alias (type A = B)? - Q33Arrays vs slices as values: what does this print?