首页 > 后端开发 > Golang > 在这个 Go 代码示例中,为什么 Loop1 打印'更新”三次,而 Loop2 打印不同的值?

在这个 Go 代码示例中,为什么 Loop1 打印'更新”三次,而 Loop2 打印不同的值?

Linda Hamilton
发布: 2024-12-11 03:53:14
原创
457 人浏览过

Why Does Loop1 Print

理解 Go 中的 For 循环行为

在编程中,某些构造可能会导致意外的行为。考虑 for 循环的这两种变体:

var cmds = []string{"create", "delete", "update"}

func loop1() {
    actions := make(map[string]func())

    for _, cmd := range cmds {
        actions[cmd] = func() {
            fmt.Println(cmd)
        }
    }
    for _, action := range actions {
        action()
    }
}

func loop2() {
    actions := make(map[string]func())

    for i, cmd := range cmds {
        command := cmds[i]
        actions[cmd] = func() {
            fmt.Println(command)
        }
    }
    for _, action := range actions {
        action()
    }
}
登录后复制

Loop1 打印“update”三次,而 Loop2 打印“delete”、“update”和“create”。为了理解这种行为,让我们深入研究细节。

循环变量参考

在loop1中,我们声明一个循环变量cmd并使用它来迭代cmds切片。然而,在嵌套循环中,变量 cmd 仍然引用外层循环中的循环变量。

闭包中的值共享

在映射中创建函数文字时actions 中,循环变量 cmd 被闭包捕获。这意味着每个函数继承对同一循环变量实例的引用,而不是副本。

Last Value Dependency

当嵌套循环完成时,循环变量 cmd 已前进到切片中的最后一个元素(“更新”)。这意味着所有闭包现在都引用最后一个元素。

结果:

在嵌套循环内打印时,所有闭包都会打印“update”,因为它们都引用中的最后一个元素相同

修复:

要解决此问题,我们使用 cmd2 := cmd 在 Loop1 中创建循环变量的副本,并在函数文字中使用该副本。这确保每个闭包在创建时都对 cmd 的值有一个不同的引用。

这一澄清强调了在闭包中引用循环变量的细微差别,并演示了仔细理解闭包如何在 Go 中捕获变量的重要性.

以上是在这个 Go 代码示例中,为什么 Loop1 打印'更新”三次,而 Loop2 打印不同的值?的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:php.cn
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
作者最新文章
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板