When iterating over a slice in Go, you may encounter unexpected behavior when using the range method. Let's delve into why different loop variations can produce different results.
Consider the following two for loop variations:
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) } } }
Running these loops results in different outputs:
The issue with loop1() arises because the function literals that are stored in the actions map reference the loop variable cmd. Since there is only one instance of this loop variable, all functions stored in the map will refer to it.
When the loop completes, the value of cmd will be the last element in the cmds slice, "update." As a result, when the functions in the actions map are executed, they will all print "update."
To circumvent this issue, loop2() captures the loop variable cmd using a new variable, command. This creates a "detached" copy of the loop variable for each iteration, which is not affected by the loop variable after the loop completes.
As a consequence, each function stored in the actions map in loop2() has its own copy of the loop variable, which allows each function to print the correct command.
When ranging over a slice, it's important to be aware that the loop variable is shared among all iterations. To avoid unexpected behavior, it's good practice to capture or detach the loop variable using a new variable, especially when using function literals that will be executed after the loop.
The above is the detailed content of Why Does Go's `range` Loop Produce Different Results with Varying Loop Structures?. For more information, please follow other related articles on the PHP Chinese website!