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

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

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

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

 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

围棋为什么设计成这样?获取切片元素的地址有什么特别之处?

推荐答案

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

如果 map 变大或变小,指向 map 元素的潜在指针可能会变成指向任何地方(未初始化内存)的悬空指针.这里的问题不是"用户困惑",而是它会打破围棋的一个主要设计元素:没有悬空的指针.

如果切片耗尽容量,则创建新的、更大的后备数组,并且将旧后备数组复制到新的中;以及旧后备数组remainsexisting.因此,从指向旧后备数组的"未增长"片获得的任何指针仍然是指向有效存储器的有效指针.

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

注意,在切片收缩期间不存在"减少切片的衬底数组".

Go相关问答推荐

在保留额外参数的同时解封YAML

GitHub发布Golang子模块

GORM Find方法中缺少字段

Golang中的泛型 struct /接口列表

Date.Format正在输出非常奇怪的日期

为什么要立即调用内联函数,而不仅仅是调用其包含的函数?

testcontainers:如何修复绑定源路径不存在

如何为ANTLR4目标Go调试监听器

使用Cookie身份验证的Gorilla Golang Websocket优化

我的神经网络(从头开始)训练,让它离目标更远

使用 Go 解组 SOAP 消息

当函数返回一个函数时,为什么 Go 泛型会失败?

对所有标志进行 ORing 的简短方法

Golang计算 struct struct 中的字段数

函数超时和 goroutine 泄漏

跟踪长时间运行的任务的进度 - 正确的方法

如何从应用程序调用谷歌云身份 API

如何使用 fyne 避免 GUI 应用程序中的循环依赖?

如何访问Go 1.18泛型 struct (structs)中的共享字段

Golang LinkedList 删除第一个元素