为什么 Go 禁止获取 (&) 映射成员的地址,而允许 (&) 切片元素? [英] Why does Go forbid taking the address of (&) map member, yet allows (&) slice element?

查看:12
本文介绍了为什么 Go 禁止获取 (&) 映射成员的地址,而允许 (&) 切片元素?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Go 不允许获取地图成员的地址:

Go doesn't allow taking the address of a map member:

// if I do this:
p := &mm["abc"]
// Syntax Error - cannot take the address of mm["abc"]

基本原理是,如果 Go 允许获取此地址,则当 map backstore 增长或缩小时,该地址可能会变得无效,从而使用户感到困惑.

The rationale is that if Go allows taking this address, when the map backstore grows or shinks, the address can become invalid, confusing the user.

但是当 Go 的切片超出其容量时会被重新定位,然而,Go 允许我们获取切片元素的地址:

But Go slice gets relocated when it outgrows its capacity, yet, Go allows us to take the address of a slice element:

 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 是这样设计的?取切片元素的地址有什么特别之处?

Why is Go designed like this? What is special about taking address of slice element?

推荐答案

切片和映射之间有一个主要区别:切片由后备数组支持,而映射没有.

There is a major difference between slices and maps: Slices are backed by a backing array and maps are not.

如果地图增长或缩小,指向地图元素的潜在指针可能会成为指向无处的悬空指针(未初始化的内存).这里的问题不是用户的困惑",而是它会破坏 Go 的一个主要设计元素:没有悬空指针.

If a map grows or shrinks a potential pointer to a map element may become a dangling pointer pointing into nowhere (uninitialised memory). The problem here is not "confusion of the user" but that it would break a major design element of Go: No dangling pointers.

如果切片容量不足,则会创建一个新的更大的后备数组,并将旧的后备数组复制到新的后备数组中;和旧的支持数组保留 现有.因此,从未生成"切片获得的指向旧支持数组的任何指针仍然是指向有效内存的有效指针.

If a slice runs out of capacity a new, larger backing array is created and the old backing array is copied into the new; and the old backing array remains existing. Thus any pointers obtained from the "ungrown" slice pointing into the old backing array are still valid pointers to valid memory.

如果您的切片仍然指向旧的支持数组(例如,因为您在将切片增长到超出其容量之前制作了该切片的副本),您仍然可以访问旧的支持数组.这与切片元素的指针关系不大,但切片是数组的视图,并且在切片增长期间复制数组.

If you have a slice still pointing to the old backing array (e.g. because you made a copy of the slice before growing the slice beyond its capacity) you still access the old backing array. This has less to do with pointers of slice elements, but slices being views into arrays and the arrays being copied during slice growth.

请注意,切片收缩期间没有减少切片的支持数组".

Note that there is no "reducing the backing array of a slice" during slice shrinkage.

这篇关于为什么 Go 禁止获取 (&) 映射成员的地址,而允许 (&) 切片元素?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆