0

Suppose there is a code snippet like this.

mapper := make(map[int]SomeStructType)
mapper[0] = SomeStructType{}

somestruct := mapper[0]   // load mapper[0] to 'somestruct'

At the last line, does that mean mapper[0] is copied to somestruct in all situations, like even if somestruct is ever used as a read-only constant afterward?

If so, is there any way to make a reference to a map element (mapper[0] here) like in C/C++, so that I can reference it through an alias while avoiding unnecessary object copy? I tried to make a pointer to a map element, but apparently, Go does not allow me to do so.

Gwangmu Lee
  • 437
  • 3
  • 12
  • 2
    Map values in Go are _not_ addressable. Suggest keep a map of `int` to a pointer to struct – Inian Aug 10 '21 at 11:47
  • Okay, I tried to avoid a pointer-typed element as I wanted to export the map in JSON, but it seems like a pointer-typed element can be exported in JSON too. https://stackoverflow.com/questions/55813574/when-to-use-a-pointer-to-a-nested-struct-for-json – Gwangmu Lee Aug 10 '21 at 11:54
  • But still this question has some points, like can't we make an alias of a map element without forcing Go to make a copy? – Gwangmu Lee Aug 10 '21 at 11:55
  • 4
    @GwangmuLee No. Map elements can be reallocated, leaving the pointer invalid. So it's simply not allowed. – super Aug 10 '21 at 12:03
  • 1
    "does that mean mapper[0] is copied to somestruct in all situations" *Every* assignment in Go is a copy. "even if somestruct is ever used as a read-only constant afterward" no such thing. Go's only constants are compile-time constants. – Adrian Aug 10 '21 at 13:32

1 Answers1

2

The simple answer is NO. In Go, the map implementation may move data around, so references would get invalidated and it wouldn't be safe. In C you define your own data structure, so it's up to you how this is done; in Go, maps are implemented in the Go runtime, and it can't guess at your intent.

The solution you're looking for, I think, is keep pointers in the map, i.e.:

mapper := make(map[int]*SomeStructType)

Now accessing mapper elements will just "copy" a pointer (typically a single word), which is very cheap.

somestruct := mapper[0] // copies a pointer

It's very common to use pointer types in Go, so you wouldn't be doing anything too magical or unusual by defining mapper like this.

Eli Bendersky
  • 263,248
  • 89
  • 350
  • 412
  • 1
    Although semantically `somestruct` is indeed a copy, the compiler can (at least theoretically) optimize it to a reference in some cases — for example, using [common-subexpression elimination](https://en.wikipedia.org/wiki/Common_subexpression_elimination) optimization (if it can prove that the map won't be modified in the meantime). – bcmills Aug 10 '21 at 13:47
  • 1
    See https://golang.org/issue/17133 for a bit more detail on what is and is not optimized at the moment. – bcmills Aug 10 '21 at 13:55