Saturday, August 15, 2026
Why Can't I Take the Address of a Map Value in Go?
Posted by

Why Can't I Take the Address of a Map Value in Go?
Because m[k] is not addressable. The compiler rejects &m[k] (and pointer-receiver calls on m[k]) so you cannot hold a pointer into a hash table that may move. Copy the value into a variable, change it, assign it back. If you need in-place mutation, store *T in the map instead of T.
The failure
package main
type User struct {
Name string
Hits int
}
func (u *User) Hit() { u.Hits++ }
func main() {
users := map[string]User{
"ada": {Name: "Ada"},
}
// cannot take address of users["ada"]
// p := &users["ada"]
// cannot call pointer method on users["ada"]
// users["ada"].Hit()
users["ada"].Hits++ // also illegal: cannot assign to struct field users["ada"].Hits
}
users["ada"] += … for a number is allowed only because it is sugar for copy, add, store. It is not an in-place update of a stable slot.
Why this happens
A map value lives in a bucket. Inserts, deletes, and growth reorganize those buckets. Keith Randall (who implemented Go maps) put it plainly: if you kept a pointer into a bucket and the map grew, that pointer would name an old bucket. Go will not let you write that dangling pointer.
Slice elements are different. They sit in a backing array at a fixed offset until append allocates a new array. The language treats &s[i] as addressable; it does not treat &m[k] that way. After delete(m, k), there is also no honest answer for what a leftover pointer should name without breaking memory safety.
The spec rule is the addressability list: variables, pointer indirection, slice/array elements, struct fields of addressable structs, and composite literals. A map index is none of those. Same family as &42 and &f().
The fix
Copy, mutate, write back — works for any value type:
u := users["ada"]
u.Hit()
users["ada"] = u
Store pointers when many call sites need to mutate:
users := map[string]*User{
"ada": {Name: "Ada"},
}
users["ada"].Hit() // the map entry is the pointer; the User does not move
A missing key still returns nil. Check before you dereference, or you have a nil-pointer panic instead of a compile error.
Do not use a pointer into a map as a long-lived identity for a record. The map is a table, not an object graph. If identity matters, keep the *User (or an ID) as the value.
Learn more: