Rumah >pembangunan bahagian belakang >Golang >Mengapakah Go Memerlukan Penyalinan Eksplisit Pembolehubah Gelung dalam Penutupan?

Mengapakah Go Memerlukan Penyalinan Eksplisit Pembolehubah Gelung dalam Penutupan?

Barbara Streisand
Barbara Streisandasal
2024-12-24 01:44:11355semak imbas

Why Does Go Require Explicit Copying of Loop Variables in Closures?

Penutupan yang Dirakam dalam Go (untuk Pembolehubah Gelung)

Pengkompil Go tidak menangkap secara automatik untuk...pembolehubah gelung julat seperti yang ditetapkan secara setempat pembolehubah penutupan. Sebaliknya, Go memperlakukan semua untuk gelung (termasuk untuk...gelung julat) dengan cara yang sama, memerlukan penyalinan eksplisit pembolehubah gelung ke dalam penutupan setempat untuk memastikan gelagat yang dijangkakan.

Penalaran untuk Menyalin Pembolehubah Gelung

Tingkah laku ini berpunca daripada pengendalian konsisten untuk gelung Go. Dalam semua jenis gelung untuk, termasuk untuk...gelung julat, pembolehubah gelung diskop kepada blok gelung. Selepas blok gelung berakhir, pembolehubah gelung tidak lagi boleh diakses.

Dalam untuk...gelung julat, pembolehubah gelung dimulakan kepada nilai baharu untuk setiap lelaran gelung. Walau bagaimanapun, penutupan yang dibuat dalam gelung terus merujuk kepada pembolehubah gelung asal. Untuk memastikan penutupan mempunyai salinan bebas pembolehubah gelung, ia mesti diberikan kepada pembolehubah setempat dalam penutupan.

Contoh Kod

Di bawah ialah contoh yang menggambarkan keperluan untuk menyalin pembolehubah gelung:

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

    l := make([]func() (int32, int32), 0)
    for k, v := range m {
        l = append(l, func() (int32, int32) {
            return k, v
        })
    }

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

Dalam contoh ini, pembolehubah gelung k dijangka berubah semasa setiap lelaran gelung untuk...julat. Walau bagaimanapun, penutupan menangkap pembolehubah gelung asal k, yang kekal sama sepanjang gelung. Akibatnya, kod mencetak pasangan nilai yang sama (10, 10) sepuluh kali.

Penyelesaian: Menyalin Pembolehubah Gelung

Untuk membetulkan isu, gelung pembolehubah mesti disalin ke dalam pembolehubah tempatan dalam penutupan:

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

    l := make([]func() (int32, int32), 0)
    for k, v := range m {
        kLocal, vLocal := k, v
        l = append(l, func() (int32, int32) {
            return kLocal, vLocal
        })
    }

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

Sekarang, penutupan menangkap pembolehubah tempatan kLocal dan vLocal, yang secara bebas memegang nilai yang diberikan semasa setiap lelaran gelung untuk...julat. Kod mencetak dengan betul pasangan nilai (1, 1), (2, 2), ..., (10, 10).

Atas ialah kandungan terperinci Mengapakah Go Memerlukan Penyalinan Eksplisit Pembolehubah Gelung dalam Penutupan?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn