Go 不允许获取地图成员的地址:
// if I do this:
p := &mm["abc"]
// Syntax Error - cannot take the address of mm["abc"]
理由是,如果 Go 允许使用此地址,那么当地图后台存储增长或缩小时,该地址可能会变得无效,从而使用户感到困惑。
但是 Go 切片在超出其容量时会被重新定位,但是 Go 允许我们获取切片元素的地址:
a := make([]Test, 5)
a[0] = Test{1, "dsfds"}
a[1] = Test{2, "sdfd"}
a[2] = Test{3, "dsf"}
addr1 := reflect.ValueOf(&a[2]).Pointer()
fmt.Println("Address of a[2]: ", addr1)
a = append(a, Test{4, "ssdf"})
addrx := reflect.ValueOf(&a[2]).Pointer()
fmt.Println("Address of a[2] After Append:", addrx)
// Note after append, the first address is invalid
Address of a[2]: 833358258224
Address of a[2] After Append: 833358266416
Go为什么要这样设计?获取切片元素的地址有什么特别之处?
切片和映射之间有一个主要区别:切片由支持数组支持,而映射则不然。
如果映射增大或缩小,则指向映射元素的潜在指针可能会变成指向任何地方的悬空指针(未初始化的内存)。这里的问题不是“用户的困惑”,而是它会破坏 Go 的一个主要设计元素:没有悬空指针。
如果切片耗尽容量,则会创建一个更大的新后备数组,并将旧后备数组复制到新数组中;和旧的支持阵列remains existing。因此,从指向旧后备数组的“未增长”切片获得的任何指针仍然是指向有效内存的有效指针。
如果您有一个切片仍然指向旧的后备数组(例如,因为您在将切片增长到超出其容量之前创建了切片的副本),您仍然可以访问旧的后备数组。这与切片元素的指针关系不大,但切片是数组的视图,并且数组在切片增长期间被复制。
请注意,在切片收缩期间不存在“减少切片的支持数组”。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)