I\'m seeing different behavior in my program that\'s tied to this particular loop in my program but I\'m not sure I understand why it\'s behaving the way it is.
The problem with loop1()
is that you store a function literal in the actions
map that references the loop variable cmd
. There is only one instance of this loop variable, so when after the loop you call the functions stored in the actions
map, all will refer to this single loop variable (which is kept because the functions / closures still have a reference to it), but its value at the time of execution will be the last value set by the for
loop, which is the last value in the cmds
slice (that is, "update"
, so you'll see "update"
printed 3 times).
An easy workaround is to make a copy of this loop variable, so each iteration, each function literal will have its own copy, which is "detached" from the loop variable:
func loop1() {
actions := make(map[string]func())
for _, cmd := range cmds {
cmd2 := cmd
actions[cmd] = func() {
fmt.Println(cmd2) // Refer to the detached, copy variable!
}
}
for _, action := range actions {
action()
}
}
With this, output of loop1()
(try it on the Go Playground):
update
create
delete
This it's not an issue of the for ... range
, it's because the closures refer to the same variable, and you don't use the value of the variable right away, only after the loop. And when you print the value of this variable, all print the same, last value of it.
Also see this possible duplicate: Golang: Register multiple routes using range for loop slices/map