Why do these two for loop variations give me different behavior?

前端 未结 1 1466
渐次进展
渐次进展 2020-12-10 20:06

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.



        
相关标签:
1条回答
  • 2020-12-10 20:11

    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

    0 讨论(0)
提交回复
热议问题