获取不到map中struct对象的指针

__Golang__ · 2020-11-06 21:40:20 · 1082 次点击 · 大约8小时之前 开始浏览    置顶
这是一个创建于 2020-11-06 21:40:20 的主题,其中的信息可能已经有所发展或是发生改变。

请教为啥无法获取stus["a"]的指针

type Student struct {
    Name string
}

func main() {
    stus := make(map[string]Student)
    stus["a"] = Student{"a"}
    p := &stus["a"]      //cannot take the address of stus["a"]
}

有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1082 次点击  
加入收藏 微博
6 回复  |  直到 2020-11-10 21:48:41
focusonline
focusonline · #1 · 4年之前

这是因为stus["a"]的返回值不是固定的地址, 算不出来吧, 因为每次都要复制一次. 你如果把stus["a"]赋值给一个栈变量就可以了.

s := stus["a"]
    //p := stus["a"]      //cannot take the address of stus["a"]
    p := &s // 这样就不会报错了
__Golang__
__Golang__ · #2 · 4年之前
focusonlinefocusonline #1 回复

这是因为stus["a"]的返回值不是固定的地址, 算不出来吧, 因为每次都要复制一次. 你如果把stus["a"]赋值给一个栈变量就可以了. ```go s := stus["a"] //p := stus["a"] //cannot take the address of stus["a"] p := &s // 这样就不会报错了 ```

谢谢大佬

avtion
avtion · #3 · 4年之前

详细请看 Go101的问答 - 为什么映射元素不可被取地址?

为什么映射元素不可被取地址?

在Go中,映射的设计保证一个映射值在内存允许的情况下可以加入任意个条目。 另外为了防止一个映射中为其条目开辟的内存段支离破碎,官方标准编译器使用了哈希表来实现映射。 并且为了保证元素索引的效率,一个映射值的底层哈希表只为其中的所有条目维护一段连续的内存段。 因此,一个映射值随着其中的条目数量逐渐增加时,其维护的连续的内存段需要不断重新开辟来增容,并把原来内存段上的条目全部复制到新开辟的内存段上。 另外,即使一个映射值维护的内存段没有增容,某些哈希表实现也可能在当前内存段中移动其中的条目。 总之,映射中的元素的地址会因为各种原因而改变。 如果映射元素可以被取地址,则Go运行时(runtime)必须在元素地址改变的时候修改所有存储了元素地址的指针值。 这极大得增加了Go编译器和运行时的实现难度,并且严重影响了程序运行效率。 因此,目前,Go中禁止取映射元素的地址。

映射元素不可被取地址的另一个原因是表达式aMap[key]可能返回一个存储于aMap中的元素,也可能返回一个不存储于其中的元素零值。 这意味着表达式aMap[key]在(&aMap[key]).Modify()调用执行之后可能仍然被估值为元素零值。 这将使很多人感到困惑,因此在Go中禁止取映射元素的地址。

__Golang__
__Golang__ · #4 · 4年之前

@avtion 谢谢:)

zzustu
zzustu · #5 · 4年之前
avtionavtion #3 回复

详细请看 [Go101的问答 - 为什么映射元素不可被取地址?](https://gfw.go101.org/article/unofficial-faq.html#map-elements-are-unaddressable) > # 为什么映射元素不可被取地址? 在Go中,映射的设计保证一个映射值在内存允许的情况下可以加入任意个条目。 另外为了防止一个映射中为其条目开辟的内存段支离破碎,官方标准编译器使用了哈希表来实现映射。 并且为了保证元素索引的效率,一个映射值的底层哈希表只为其中的所有条目维护一段连续的内存段。 因此,一个映射值随着其中的条目数量逐渐增加时,其维护的连续的内存段需要不断重新开辟来增容,并把原来内存段上的条目全部复制到新开辟的内存段上。 另外,即使一个映射值维护的内存段没有增容,某些哈希表实现也可能在当前内存段中移动其中的条目。 总之,映射中的元素的地址会因为各种原因而改变。 如果映射元素可以被取地址,则Go运行时(runtime)必须在元素地址改变的时候修改所有存储了元素地址的指针值。 这极大得增加了Go编译器和运行时的实现难度,并且严重影响了程序运行效率。 因此,目前,Go中禁止取映射元素的地址。 > 映射元素不可被取地址的另一个原因是表达式aMap[key]可能返回一个存储于aMap中的元素,也可能返回一个不存储于其中的元素零值。 这意味着表达式aMap[key]在(&aMap[key]).Modify()调用执行之后可能仍然被估值为元素零值。 这将使很多人感到困惑,因此在Go中禁止取映射元素的地址。

go101不错,就是读起来像翻译的外文

avtion
avtion · #6 · 4年之前
zzustuzzustu #5 回复

#3楼 @avtion go101不错,就是读起来像翻译的外文

应该就是每一个字都看得懂,连起来就不懂了

添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传