理解 Go 中的 For 循環行為
在程式設計中,某些構造可能會導致意外的行為。考慮 for 迴圈的這兩種變體:
var cmds = []string{"create", "delete", "update"} func loop1() { actions := make(map[string]func()) for _, cmd := range cmds { actions[cmd] = func() { fmt.Println(cmd) } } for _, action := range actions { action() } } 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」三次,而 Loop2 列印「delete」、「update」和「create」。為了理解這種行為,讓我們深入研究細節。
循環變數參考
在loop1中,我們聲明一個循環變數cmd並使用它來迭代cmds切片。然而,在嵌套循環中,變數 cmd 仍然引用外層循環中的循環變數。
閉包中的值共享
在映射中建立函數文字時actions 中,循環變數 cmd 被閉包捕獲。這意味著每個函數繼承對同一循環變數實例的引用,而不是副本。
Last Value Dependency
當巢狀循環完成時,循環變數 cmd 已前進到切片中的最後一個元素(「更新」)。這意味著所有閉包現在都引用最後一個元素。
結果:
在嵌套循環內打印時,所有閉包都會打印“update”,因為它們都引用中的最後一個元素相同
修正:
要解決此問題,我們使用cmd2 := cmd 在 Loop1 中建立循環變數的副本,並在函數文字中使用該副本。這確保每個閉包在建立時都對 cmd 的值有一個不同的參考。
這一澄清強調了在閉包中引用循環變量的細微差別,並演示了仔細理解閉包如何在 Go 中捕獲變量的重要性.
以上是在這個 Go 程式碼範例中,為什麼 Loop1 會列印「更新」三次,而 Loop2 會列印不同的值?的詳細內容。更多資訊請關注PHP中文網其他相關文章!