Dans Go, le compilateur peut capturer automatiquement les variables de boucle pour les utiliser dans fermetures, mais ce comportement varie en fonction du type de boucle. Dans les boucles for...range, les variables de boucle sont capturées comme références aux variables d'itération de la boucle externe.
Go traite for.. Boucles .range et autres boucles for de la même manière. Par conséquent, la fermeture capturée pour une variable de boucle dans une boucle for...range fait référence au même emplacement mémoire que la variable de la boucle externe.
Dans ce scénario, toute modification apportés à la variable de fermeture capturée affectent également la variable de la boucle externe, conduisant potentiellement à un comportement inattendu. Pour éviter ce problème, il est nécessaire de créer une copie de la variable de boucle dans la fermeture, comme indiqué dans l'exemple « Valeur...plage » ci-dessous.
Le code fourni L'extrait illustre la différence entre capturer une référence à la variable de boucle et capturer sa valeur :
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) } }
In lab1, les fermetures capturées font référence aux valeurs finales de la boucle au lieu des valeurs individuelles attendues. Dans Lab2, les captures font toujours référence aux valeurs finales car la fermeture créée utilise les mêmes variables de boucle qui sont référencées ailleurs dans la portée externe. Dans Lab3, les fermetures capturent des copies des variables de boucle, elles représentent donc avec précision les valeurs individuelles.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!