为什么Go语言中使用for range循环遍历切片时,map中所有值指向同一内存地址?

为什么Go语言中使用for range循环遍历切片时,map中所有值指向同一内存地址?

go语言for…range循环map的陷阱

本文分析一个常见的Go语言编程问题,该问题涉及到结构体切片和map的用法,并解释了为什么使用for…range循环遍历切片时,map中所有值会指向同一内存地址。理解这个问题对于掌握Go语言的内存管理和引用类型至关重要。

问题描述:

以下代码片段演示了该问题:

立即学习go语言免费学习笔记(深入)”;

type student struct {     name string     age  int }  func main() {     m := make(map[string]*student)     stus := []student{         {name: "pprof.cn", age: 18},         {name: "测试", age: 23},         {name: "博客", age: 28},     }      for _, stu := range stus {         m[stu.name] = &stu     }     for k, v := range m {         fmt.Println(k, "=>", v.name)     } }

运行结果显示所有v.name的值都为”博客”。这是因为for…range循环在遍历切片时,stu变量是一个循环内部的临时变量,其内存地址在每次迭代中都指向同一个内存位置。 因此,m[stu.name] = &stu 实际上将map中的所有值都指向了同一个student结构体的内存地址,而这个地址在循环结束后指向的是最后一个元素”博客”。

解决方案:

为了避免这个问题,应该在循环中使用切片的索引来获取元素的地址,如下所示:

for i := range stus {     m[stus[i].name] = &stus[i] }

这种方法确保每个student结构体的地址都是独立的,从而避免了所有值指向同一内存地址的问题。

总结:

此问题揭示了Go语言for…range循环的特性以及引用类型的行为。理解for…range循环中临时变量的生命周期,以及如何正确地处理引用类型,对于编写高效且无错误的Go代码至关重要。 正确使用索引访问切片元素,可以避免此类内存管理陷阱。

以上就是

© 版权声明
THE END
喜欢就支持一下吧
点赞6 分享