2016-07-03 43 views
4

在使用Go代码时,我发现地图值不可寻址。例如,为什么地图值不可寻址?

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) 
} 

生成错误

mapaddressable.go:7:不能采取MyMap中的地址[1]

然而,代码,

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) 
} 

完美无瑕。

这是为什么? Go开发人员为什么选择使某些值不可寻址?这是语言的缺点还是特点?

编辑: 从C++作为背景,我不习惯,这似乎是在围棋盛行这种not addressable趋势。例如,下面的代码工作得很好:

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

这将是很好,如果有人能指出为什么同一寻址无法实现(或故意没有实现)在Go。

+1

另请参见http://stackoverflow.com/questions/20224478/dereferencing-a-map-index-in-golang – nos

+1

正如最佳答案所述,它是一个散列表,它将值存储在存储区中。当它重新绘制值时,如果你想解决这个问题,使用指针作为你的值类型将做到这一点。 – twotwotwo

+0

C++'map'摆脱了这个,因为它们是二叉树,不需要移动RAM中的现有节点来添加新节点(但其操作平均为O(log n),而不是O(1))。 C++'unordered_map'是一个哈希表,但必须对实现施加某些限制才能避免值移动; http://stackoverflow.com/a/31113618/2714852和http://stackoverflow.com/q/37428119/讨论。 – twotwotwo

回答

8

嗯,我不知道地图的内部Go实现,但很可能它是一种哈希表。因此,如果您保存其中一个条目的地址,然后再放入一堆条目,则您保存的地址可能无效。这是由于哈希表的内部重组导致加载因子超过某个阈值并且哈希表需要增长。
因此我想不允许为了避免这样的错误而采取其中一个条目的地址。

+0

也有人指出:https://github.com/golang/go/issues/11865 – weaming

相关问题