首页 > 后端开发 > Golang > 正文

Go编程中的陷阱:为什么代码中输出的名字都是“博客”?

霞舞
发布: 2025-03-19 10:18:21
原创
958人浏览过

go编程中的陷阱:为什么代码中输出的名字都是“博客”?

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循环及指针的用法。

问题根源:循环变量复用与指针指向

  1. 循环变量复用: Go语言的for...range循环会复用循环变量stu。这意味着stu始终指向同一内存地址。

  2. 指针引用: 代码中m[stu.name] = &stu使用指针,每次迭代都将stu的内存地址赋值给map。由于stu的地址不变,所有map的值都指向同一地址。

  3. 最后一次赋值: 循环结束后,stu保存了最后一个学生的信息(“博客”)。因此,map中所有键值都指向这个最终的stu地址。

    Noiz Agent
    Noiz Agent

    AI声音创作Agent平台

    Noiz Agent 323
    查看详情 Noiz Agent
  4. 输出结果: 打印v.name时,所有指针都指向同一个“博客”数据,故输出结果全为“博客”。

解决方案:避免指针直接引用循环变量

为了避免此问题,应在循环内创建新的student结构体副本,而不是直接使用stu的指针:

for _, stu := range stus {
    s := stu // 创建副本
    m[stu.name] = &s
}
登录后复制

这样,每个map的键值对都指向不同的内存地址,从而正确输出每个学生的名字。

总结:谨慎使用指针和理解循环变量

此例警示我们在Go语言中使用指针时需格外谨慎,尤其在循环和切片操作中。理解for...range循环的变量复用机制是避免此类问题的关键。 避免直接将循环变量的地址赋值给map或其他数据结构,而是创建副本后再使用指针,是更安全的做法。

以上就是Go编程中的陷阱:为什么代码中输出的名字都是“博客”?的详细内容,更多请关注php中文网其它相关文章!

最佳 Windows 性能的顶级免费优化软件
最佳 Windows 性能的顶级免费优化软件

每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。

下载
来源:php中文网
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
最新问题
开源免费商场系统广告
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新 English
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号