
Go语言陷阱:循环与指针的误用导致输出全为“博客”
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) }}
运行结果令人意外:所有输出均为“博客”。究其原因,在于for...range循环及指针的用法。
问题根源:循环变量复用与指针指向
循环变量复用: Go语言的for...range循环会复用循环变量stu。这意味着stu始终指向同一内存地址。
指针引用: 代码中m[stu.name] = &stu使用指针,每次迭代都将stu的内存地址赋值给map。由于stu的地址不变,所有map的值都指向同一地址。
最后一次赋值: 循环结束后,stu保存了最后一个学生的信息(“博客”)。因此,map中所有键值都指向这个最终的stu地址。
输出结果: 打印v.name时,所有指针都指向同一个“博客”数据,故输出结果全为“博客”。
解决方案:避免指针直接引用循环变量
为了避免此问题,应在循环内创建新的student结构体副本,而不是直接使用stu的指针:
for _, stu := range stus { s := stu // 创建副本 m[stu.name] = &s}
这样,每个map的键值对都指向不同的内存地址,从而正确输出每个学生的名字。
总结:谨慎使用指针和理解循环变量
此例警示我们在Go语言中使用指针时需格外谨慎,尤其在循环和切片操作中。理解for...range循环的变量复用机制是避免此类问题的关键。 避免直接将循环变量的地址赋值给map或其他数据结构,而是创建副本后再使用指针,是更安全的做法。
以上就是Go编程中的陷阱:为什么代码中输出的名字都是“博客”?的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1386186.html
微信扫一扫
支付宝扫一扫