Dalam Go, pengkompil boleh menangkap pembolehubah gelung secara automatik untuk digunakan dalam penutupan, tetapi tingkah laku ini berbeza-beza bergantung pada jenis gelung. Dalam untuk...gelung julat, pembolehubah gelung ditangkap sebagai rujukan kepada pembolehubah lelaran gelung luar.
Go treats for.. .gelung julat dan lain-lain untuk gelung yang serupa. Oleh itu, penutupan yang ditangkap untuk pembolehubah gelung dalam gelung untuk...julat merujuk lokasi memori yang sama seperti pembolehubah gelung luar.
Dalam senario ini, sebarang pengubahsuaian dibuat pada pembolehubah penutupan yang ditangkap juga mempengaruhi pembolehubah gelung luar, yang berpotensi membawa kepada tingkah laku yang tidak dijangka. Untuk mengelakkan isu ini, anda perlu membuat salinan pembolehubah gelung dalam penutupan, seperti yang ditunjukkan dalam contoh "Nilai...julat" di bawah.
Kod yang disediakan coretan menggambarkan perbezaan antara menangkap rujukan kepada pembolehubah gelung berbanding menangkapnya value:
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) } }
Dalam makmal1, penutupan yang ditangkap merujuk nilai akhir daripada gelung dan bukannya nilai individu yang dijangkakan. Dalam makmal2, tangkapan masih merujuk nilai akhir kerana penutupan yang dibuat menggunakan pembolehubah gelung yang sama yang dirujuk di tempat lain dalam skop luar. Dalam makmal3, penutupan menangkap salinan pembolehubah gelung, jadi ia mewakili nilai individu dengan tepat.
Atas ialah kandungan terperinci Bagaimana Go Mengendalikan Pembolehubah Gelung Ditangkap dalam Penutupan, dan Mengapa Ia Penting?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!