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 de plage ?

Pourquoi la fonction « append » de Go produit-elle des résultats inattendus lors de l'ajout de pointeurs à partir d'une boucle de plage ?

Patricia Arquette
Patricia Arquetteoriginal
2024-12-08 03:08:11206parcourir

Why Does Go's `append` Function Produce Unexpected Results When Appending Pointers from a Range Loop?

Écrasement involontaire dans la fonction « ajouter » de Go

Dans Go, explorer les nuances de l'ajout à des tranches peut parfois conduire à des résultats inattendus. Examinons un exemple illustrant ce comportement.

Considérez le code suivant :

import "fmt"

type Foo struct {
    val int
}

func main() {
    a := make([]*Foo, 1)
    a[0] = &Foo{0}

    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)
    }
}

Curieusement, au lieu d'imprimer {0} {1} {2} {3}, la sortie se lit comme {0} {3} {3} {3}. Pour résoudre ce casse-tête, disséquons la fonction "append".

Dans Go, "append" attend un pointeur vers la tranche à laquelle nous ajoutons des éléments. Dans notre exemple, nous stockons correctement les pointeurs vers les instances « Foo » dans la tranche « a ».

Cependant, lors de la boucle sur les éléments du tableau « b », nous rencontrons un problème subtil. La syntaxe "range" parcourt une copie de chaque élément plutôt que l'élément lui-même. Par conséquent, nous ajoutons systématiquement des pointeurs vers des copies de l'instance "Foo" "e", qui pointe vers "Foo{3}" dans l'itération finale.

Pour corriger ce comportement, nous devons référencer les éléments réels de "b" dans notre opération "ajouter" :

for i := range b {
    a = append(a, &b[i])
}

Cette modification garantit que nous ajoutons des pointeurs directement aux éléments dans "b", ce qui donne le résultat souhaité : {0} {1} {2} {3}.

Comprendre la raison sous-jacente de ce comportement est crucial. Dans Go, les pointeurs sont des valeurs, interprétées comme des adresses mémoire lors de la manipulation des données. En tant que telles, les boucles « plage » parcourent des copies de valeurs plutôt que les objets d'origine. Cette connaissance aide à comprendre pourquoi dans notre code initial, trois éléments pointaient vers la même instance "Foo{3}".

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!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn