Accessing struct fields inside a map value (without copying)

The fundamental problem is that you can't take the address of an item within a map. You might think the compiler would re-arrange users[5].name = "Mark" into this

(&users[5]).name = "Mark"

But that doesn't compile, giving this error

cannot take the address of users[5]

This gives the maps the freedom to re-order things at will to use memory efficiently.

The only way to change something explicitly in a map is to assign value to it, i.e.

t := users[5]
t.name = "Mark"
users[5] = t

So I think you either have to live with the copy above or live with storing pointers in your map. Storing pointers have the disadvantage of using more memory and more memory allocations, which may outweigh the copying way above - only you and your application can tell that.

A third alternative is to use a slice - your original syntax works perfectly if you change users := make(map[int]User) to users := make([]User, 10)


  1. Maps are typically sparsely filled hash tables which are reallocated when they exceed the threshold. Re-allocation would create issues when someone is holding the pointers to the values
  2. If you are keen on not creating the copy of the object, you can store the pointer to the object itself as the value
  3. When we are referring the map, the value returned is returned "returned by value", if i may borrow the terminology used in function parameters, editing the returned structure does not have any impact on the contents of the map

Tags:

Go