Comprendre un comportement étrange avec ajout dans Go
Dans Go, la fonction d'ajout opère sur des tranches pour ajouter de nouveaux éléments. Cependant, les utilisateurs peuvent rencontrer un comportement inattendu lors de l'ajout de pointeurs vers des éléments d'un tableau dans une boucle for range.
Prenons l'exemple suivant :
import "fmt" type Foo struct { val int } func main() { var a = make([]*Foo, 1) a[0] = &Foo{0} var b = [3]Foo{Foo{1}, Foo{2}, Foo{3}} for _, e := range b { a = append(a, &e) } for _, e := range a { fmt.Printf("%v ", *e) } }
Résultat attendu : {0} {1} {2} {3}
Résultat réel : {0} {3} {3} {3}
Raison du comportement
Ce comportement inattendu se produit parce que la boucle for range parcourt une copie des éléments, et non les éléments d'origine eux-mêmes. Dans ce cas, la variable de boucle e contient une copie de l'élément actuel du tableau. Lorsque la tranche est ajoutée, l'adresse de la variable de boucle est ajoutée, qui fait référence au même emplacement mémoire pour toutes les itérations. Par conséquent, lorsque le dernier élément du tableau est rencontré, toutes les adresses ajoutées pointent vers le même élément.
Correction
Pour résoudre ce problème, la fonction d'ajout doit être utilisé avec l'adresse de l'élément de tableau d'origine, pas la variable de boucle. Voici le code corrigé :
for i := range b { a = append(a, &b[i]) }
Avec cette modification, le résultat sera comme prévu : {0} {1} {2} {3}.
Conclusion
Comprendre la différence entre les pointeurs et les types non-pointeurs dans Go est crucial pour une bonne gestion des références mémoire. Lorsque vous utilisez des boucles for range, il est essentiel de déterminer si vous devez accéder à l'élément d'origine ou à une copie, et d'utiliser la syntaxe appropriée en conséquence.
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!