在玩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中无法实现相同的可寻址性(或故意无法实现),那将是很好的。
答案 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中,地图值可寻址性不是必需的。