Rumah >pembangunan bahagian belakang >Golang >Mengapakah Go Memerlukan Penyalinan Eksplisit Pembolehubah Gelung dalam Penutupan?
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!