Home > Backend Development > Golang > Why Does Go's `for range` Loop Exhibit Different Behavior with Function Literals?

Why Does Go's `for range` Loop Exhibit Different Behavior with Function Literals?

Susan Sarandon
Release: 2024-12-10 20:52:11
Original
421 people have browsed it

Why Does Go's `for range` Loop Exhibit Different Behavior with Function Literals?

Understanding Different Loop Behavior in Go

When constructing loops in Go, it's crucial to understand the behavior of the for range loop. Consider the following two loop variations that exhibit distinct behavior:

Loop Variation 1:

func loop1() {

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

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

Loop Variation 2:

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()
    }
}
Copy after login

Output Observations:

  • Loop1 produces output: "update" (repeated 3 times)
  • Loop2 produces output: "delete", "update", "create"

Underlying Issue in Loop Variation 1:

The problem lies in the func loop1() loop. Each loop iteration assigns a function literal to the actions map. This function literal references the loop variable cmd. However, there is only one instance of cmd, and when the loop finishes, it holds the last value in the commands slice, which is "update." This means that all enclosed functions reference the same loop variable (cmd), which results in all functions printing "update" when called.

Solution:

To rectify this, make a copy of the loop variable within each loop iteration, so each function literal has its own independent copy:

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()
    }
}
Copy after login

Conclusion:

In conclusion, when using the for range loop, it's critical to consider the scope and references of loop variables. Ensuring that copies of loop variables are made when necessary ensures correct behavior, particularly when dealing with function literals that reference those variables.

The above is the detailed content of Why Does Go's `for range` Loop Exhibit Different Behavior with Function Literals?. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template