为什么地图值不可寻址?

时间:2016-07-03 08:55:47

标签: go

在玩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 ++背景,我不习惯这种似乎在Go中流行的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中无法实现相同的可寻址性(或故意无法实现),那将是很好的。

2 个答案:

答案 0 :(得分:12)

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

答案 1 :(得分:0)

  

来自C ++背景。

     

为什么[Go]映射值无法寻址?


如果所有其他语言都像C ++,那么拥有其他语言将毫无意义。

C ++是一种复杂的,难以阅读的语言。

Remember the Vasa! - Bjarne Stroustrup

按设计,Go是一种简单易读的语言。

dotGo 2015 - Rob Pike - Simplicity is Complicated


Go映射是一个哈希映射。确定性哈希函数应用于映射键。哈希值用于确定条目(键值对)的主映射存储桶。值区会储存一个或多个地图项目。主存储桶可能溢出到辅助存储桶。存储桶被实现为一个数组。随着插入的地图条目数量的增加,哈希函数将适应提供更多存储桶的需求。映射条目将增量复制到新的更大存储桶阵列中。如果映射条目的数量因删除而减少,则可以回收空间。

总而言之,Go地图是一种动态的,自组织的数据结构。条目(键值对)的内存地址不固定。因此,映射值不可寻址。

GopherCon 2016 Keith Randall - Inside the Map Implementation

在Go中,地图值可寻址性不是必需的。