首頁 >後端開發 >Golang >Go 如何處理閉包中捕獲的循環變量,以及為什麼它很重要?

Go 如何處理閉包中捕獲的循環變量,以及為什麼它很重要?

Mary-Kate Olsen
Mary-Kate Olsen原創
2024-12-15 11:56:10805瀏覽

How Does Go Handle Captured Loop Variables in Closures, and Why Does it Matter?

Go 中捕獲的閉包(for 循環變數)

理解循環變數閉包

在Go 中,編譯器可以自動捕捉循環變數以在內部使用閉包,但這種行為會根據循環類型而變化。在 for...range 循環中,循環變數被捕獲為對外循環迭代變數的引用。

for...range 迴圈中引用閉包的原因

Go 對待 for.. .range 迴圈和其他 for 迴圈類似。因此,for...range 循環中循環變數的捕獲閉包引用與外循環變數相同的記憶體位置。

引用閉包的後果

在這種情況下,任何修改對捕獲的閉包變量所做的操作也會影響外循環的變量,可能會導致意外的行為。為了避免這個問題,有必要在閉包中建立循環變數的副本,如下面的「Value...range」範例所示。

範例程式碼

提供的程式碼片段說明了擷取循環變數的引用與擷取其值之間的區別:

func main() {
    lab1() // captured closure is not what is expected

    lab2() // captured closure is not what is expected

    lab3() // captured closure behaves ok
}

func lab3() {
    m := make(map[int32]int32)
    for i := 1; i <= 10; i++ {
        m[i] = i
    }

    l := [](func() (int32, int32)){}
    for k, v := range m {
        kLocal, vLocal := k, v // (C) captures just the right values assigned to k and v
        l = append(l, func() (int32, int32) {
            return kLocal, vLocal
        })
    }

    for _, x := range l {
        k, v := x()
        fmt.Println(k, v)
    }
}

func lab2() {
    m := make(map[int32]int32)
    for i := 1; i <= 10; i++ {
        m[i] = i
    }

    l := [](func() (int32, int32)){}
    for k, v := range m {
        l = append(l, func() (int32, int32) {
            kLocal, vLocal := k, v // (B) captures just the last values assigned to k and v from the range
            return kLocal, vLocal
        })
    }

    for _, x := range l {
        k, v := x()
        fmt.Println(k, v)
    }
}

func lab1() {
    m := make(map[int32]int32)
    for i := 1; i <= 10; i++ {
        m[i] = i
    }

    l := [](func() (int32, int32)){}
    for k, v := range m {
        l = append(l, func() (int32, int32) { return k, v }) // (A) captures just the last values assigned to k and v from the range
    }

    for _, x := range l {
        k, v := x()
        fmt.Println(k, v)
    }
}

輸出

在lab1 中,捕獲的閉包引用循環中的最終值而不是預期的單一值。在 lab2 中,擷取仍然引用最終值,因為建立的閉包使用與外部作用域中其他地方引用的相同循環變數。在 lab3 中,閉包會擷取循環變數的副本,因此它們準確地表示各個值。

以上是Go 如何處理閉包中捕獲的循環變量,以及為什麼它很重要?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

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