首頁 >後端開發 >Golang >為什麼 Go 的「for range」迴圈與函數文字表現出不同的行為?

為什麼 Go 的「for range」迴圈與函數文字表現出不同的行為?

Susan Sarandon
Susan Sarandon原創
2024-12-10 20:52:11428瀏覽

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

了解 Go 中不同的循環行為

在 Go 中構造循環時,了解 for range 循環的行為至關重要。考慮以下兩個表現出不同行為的循環變體:

循環變體1:

func loop1() {

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

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

循環變體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()
    }
}

輸出觀察:

  • Loop1 產生輸出:「update」(重複3 次)
  • Loop2 產生輸出:「delete」、「 update」、「create」

循環變化中的根本問題1:

問題出在 func Loop1() 循環上。每次循環迭代都會在操作映射中分配一個函數文字。此函數文字引用循環變數 cmd。然而,只有一個 cmd 實例,當循環結束時,它會保存命令片中的最後一個值,即「update」。這意味著所有封閉的函數引用相同的循環變數(cmd),這會導致所有函數在呼叫時列印「update」。

解決方案:

要修正這個問題,在每次循環迭代中製作循環變數的副本,因此每個函數字面量都有自己獨立的複製:

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()
    }
}

結論:

綜上所述,在使用for range 循環時,考慮循環變數的範圍和引用至關重要。確保在必要時建立循環變數的副本可確保正確的行為,特別是在處理引用這些變數的函數文字時。

以上是為什麼 Go 的「for range」迴圈與函數文字表現出不同的行為?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn