Maison >développement back-end >Golang >Pourquoi la fonction « append » de Go produit-elle des résultats inattendus lors de l'ajout de pointeurs à partir d'une boucle for-range ?
Comportement d'ajout inattendu avec les tranches Go : une explication
Dans Go, la fonction d'ajout se comporte de manière intrigante lors de l'ajout à une tranche de pointeurs. Pour illustrer cela, considérons le code 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) } }
Contrairement à ce que l'on pensait que le code imprimerait {0} {1} {2} {3}, il imprime à la place {0} {3} { 3} {3}. La raison derrière cet écart réside dans la nature de la variable de plage de la boucle for.
Comprendre la variable de plage
La boucle for-range dans Go fonctionne en créant une copie de chaque élément du tableau ou de la tranche en cours d'itération. Dans ce cas, e est une copie de l’élément du tableau b. Par conséquent, e lui-même n’est pas l’élément de b ; il s'agit plutôt d'une variable temporaire contenant la valeur de l'élément.
Lors de l'ajout à la tranche a, le code ajoute l'adresse de e, pas l'adresse de l'élément réel dans b. Puisque e est la même copie pour toutes les itérations, le même pointeur est ajouté à a trois fois. Ainsi, la dernière valeur attribuée à e (qui est Foo{3}) est celle imprimée à plusieurs reprises.
Correction du comportement
Pour rectifier ce comportement, le code doit ajouter l'adresse de l'élément réel dans b, pas l'adresse de e. La boucle corrigée ressemblerait à ceci :
for i := range b { a = append(a, &b[i]) }
En ajoutant &b[i] au lieu de &e, le code garantit que chaque élément de b est ajouté à a. Par conséquent, le résultat correct {0} {1} {2} {3} est imprimé.
Raison du comportement initial
Ce comportement inattendu provient de l'absence de vraies références en Go. Go a des types de pointeurs et des types non-pointeurs, mais pas de références. La variable range est simplement une variable locale, contenant une valeur qui peut être un pointeur ou non. Il ne peut pas contenir de référence.
Par conséquent, lorsqu'on opère sur la variable de plage, on manipule uniquement la valeur, pas l'élément lui-même. Pour modifier l'élément réel, il faut attribuer la valeur à la variable de plage, copiant ainsi la valeur. Cette valeur est ensuite écrasée lors de l'itération suivante.
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!