13

While playing with Go code, I found out that map values are not addressable. For example,

package main
import "fmt"

func main(){
    var mymap map[int]string = make(map[int]string)
    mymap[1] = "One"
    var myptr *string = &mymap[1]
    fmt.Println(*myptr)
}

Generates error

mapaddressable.go:7: cannot take the address of mymap[1]

Whereas, the code,

package main
import "fmt"

func main(){
    var mymap map[int]string = make(map[int]string)
    mymap[1] = "One"
    mystring := mymap[1]
    var myptr *string = &mystring
    fmt.Println(*myptr)
}

works perfectly fine.

Why is this so? Why have the Go developers chosen to make certain values not addressable? Is this a drawback or a feature of the language?

Edit: Being from a C++ background, I am not used to this not addressable trend that seems to be prevalent in Go. For example, the following code works just fine:

#include<iostream>
#include<map>
#include<string>
using namespace std;
int main(){
    map<int,string> mymap;
    mymap[1] = "one";
    string *myptr = &mymap[1];
    cout<<*myptr;
}

It would be nice if somebody could point out why the same addressability cannot be achieved (or intentionally wasn't achieved) in Go.

4
  • 2
    See also stackoverflow.com/questions/20224478/… Commented Jul 3, 2016 at 15:30
  • 3
    As top answer says, it's a hashtable that stores values in the buckets. When it rehashes the values move. If you want to get around this, using a pointer as your value type will do it. Commented Jul 4, 2016 at 7:22
  • C++ maps get away with this because they're binary trees that needn't move existing nodes around in RAM to add new ones (but its operations average O(log n), not O(1)). C++ unordered_map is a hashtable, but has to impose certain restrictions on implementations to avoid values moving; stackoverflow.com/a/31113618/2714852 and stackoverflow.com/q/37428119 discuss. Commented Jul 4, 2016 at 7:35
  • I think you mean map is addressable (e.g &m), but map elements are not addressable (e.g &(m[1])), that's different. Commented Jul 29, 2018 at 13:19

2 Answers 2

21
+500

Well I do not know about the internal Go implementation of maps but most likely it is a kind of hash table. So if you take and save the address of one of its entries and afterwards put another bunch of entries into it, your saved address may be invalid. This is due to internal reorganizations of hash tables when the load factor exceeds a certain threshold and the hash table needs to grow.
Therefore I guess it is not allowed to take the address of one of its entries in order to avoid such errors.

Sign up to request clarification or add additional context in comments.

3 Comments

However, it appears that slice indexing is addressable. Shouldn't this happen to slices too, when they grow on appending?
Exactly my doubt as well ? @powersource97 did you figure this out ?
youtube.com/… by "map implementor himself" on why and and brief comparison with C++ implementation. Credit: stackoverflow.com/a/49249710/238003
1

Being from a C++ background.

Why are [Go] map values not addressable?


If all other languages were like C++ there would be no point in having other languages.

C++ is a complex, hard-to-read language.

Remember the Vasa! - Bjarne Stroustrup

Go, by design, is a simple, readable language.

dotGo 2015 - Rob Pike - Simplicity is Complicated


A Go map is a hash map. A deterministic hash function is applied to a map key. The hash value is used to determine the primary map bucket for the entry (key-value pair). A bucket stores one or more map entries. A primary bucket may overflow to secondary buckets. Buckets are implemented as an array. As the number of map entries increases by insertion, the hash function adapts to provide more buckets. The map entries are copied incrementally to a new, larger bucket array. If the number of map entries decreases by deletion, space may be reclaimed.

In summary, a Go map is a dynamic, self-organizing data structure. The memory address of an entry (key-value pair) is not fixed. Therefore, map values are not addressable.

GopherCon 2016 Keith Randall - Inside the Map Implementation

In Go, map value addressability is not necessary.

2 Comments

Slices are also self organizing i.e. they also copy over to new locations when you append more elements into it, but yet it is allowed to take address of any element in a slice.
youtube.com/… by "map implementor himself" on why and and brief comparison with C++ implementation. Credit: stackoverflow.com/a/49249710/238003

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.