在 Go 中迭代切片时,使用 range 方法时可能会遇到意外行为。让我们深入研究一下为什么不同的循环变体会产生不同的结果。
考虑以下两个 for 循环变体:
loop1() { for _, cmd := range cmds { // Store a function literal that references the loop variable cmd actions[cmd] = func() { fmt.Println(cmd) } } }
loop2() { for i, cmd := range cmds { // Capture the loop variable cmd using a new variable command := cmds[i] actions[cmd] = func() { fmt.Println(command) } } }
运行这些循环结果在不同的输出:
loop1() 出现问题是因为存储在操作映射中的函数文字引用了循环变量 cmd。由于此循环变量只有一个实例,因此存储在映射中的所有函数都会引用它。
循环完成时,cmd 的值将是 cmds 切片中的最后一个元素“update. ”因此,当执行 actions 映射中的函数时,它们都会打印“update”。
为了规避这个问题,loop2() 使用新变量 command 捕获循环变量 cmd。这会为每次迭代创建循环变量的“独立”副本,循环完成后不受循环变量的影响。
因此,loop2() 中存储在操作映射中的每个函数都有它自己的循环变量副本,它允许每个函数打印正确的命令。
在切片上进行范围操作时,重要的是要注意循环变量在所有迭代之间共享。为了避免意外行为,最好使用新变量捕获或分离循环变量,特别是在使用将在循环后执行的函数文字时。
以上是为什么 Go 的'range”循环会因循环结构的不同而产生不同的结果?的详细内容。更多信息请关注PHP中文网其他相关文章!