Maison > développement back-end > Golang > Pourquoi les tranches ajoutées dans une boucle présentent-elles un comportement inattendu lors de la création de nouvelles tranches dans Go ?

Pourquoi les tranches ajoutées dans une boucle présentent-elles un comportement inattendu lors de la création de nouvelles tranches dans Go ?

Linda Hamilton
Libérer: 2024-11-02 19:10:03
original
324 Les gens l'ont consulté

Why do slices appended in a loop exhibit unexpected behavior when creating new slices in Go?

Comportement inattendu d'ajout de tranche dans Go

Dans le domaine de la programmation Go, un comportement inhabituel a été rencontré lors de l'ajout d'éléments à une tranche dans une boucle et ensuite essayer de créer de nouvelles tranches en fonction du résultat de la boucle. Curieusement, la dernière opération d'ajout remplace les tranches créées à partir des ajouts précédents.

Exploration du problème

Considérez l'extrait de code suivant :

<code class="go">func create(iterations int) []int {
    a := make([]int, 0)
    for i := 0; i < iterations; i++ {
        a = append(a, i)
    }
    return a
}</code>
Copier après la connexion

Lors de l'appel de create(11) et de la création de nouvelles tranches en y ajoutant des éléments (c'est-à-dire j := append(i, 100), g := append(i, 101), h := append(i, 102)), un on s'attendrait à ce que les derniers éléments de ces tranches (j, g et h) soient respectivement 100, 101 et 102. Cependant, étonnamment, dans ce cas, ils finissent tous par être 102.

Ce comportement contraste fortement avec ce qui se passe lors de la création de nouvelles tranches à partir d'un littéral de tranche, comme démontré ci-dessous :

<code class="go">func sliceFromLiteral() {
    i := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    j := append(i, 100)
    g := append(i, 101)
    h := append(i, 102)
    fmt.Printf("i: %v\nj: %v\ng: %v\nh:%v\n", i, j, g, h)
}</code>
Copier après la connexion

Dans ce cas, j, g et h présentent le comportement attendu, les derniers éléments étant respectivement 100, 101 et 102.

Explorer la cause profonde

Pour percer le mystère derrière ce comportement inattendu, il est crucial de comprendre que l'opération d'ajout modifie non seulement le tableau sous-jacent, mais renvoie également une nouvelle tranche. Cela implique que les tranches j, g et h pointent en fait vers le même tableau sous-jacent. Par conséquent, lorsque le dernier ajout (append(i, 102)) est effectué, il modifie le dernier élément du tableau sous-jacent, remplaçant ainsi les valeurs de j, g et h.

L'idiomatique Solution

Pour éviter ce comportement inattendu, il est impératif de copier la tranche avant de tenter tout ajout. Cela crée un nouveau tableau sous-jacent, garantissant que la tranche d'origine reste inchangée. Le code suivant illustre la manière idiomatique de créer plusieurs nouvelles tranches basées sur celles existantes :

<code class="go">func makeFromSlice(sl []int) []int {
    result := make([]int, len(sl))
    copy(result, sl)
    return result
}</code>
Copier après la connexion

En employant cette approche, on peut créer sans effort de nouvelles tranches tout en préservant l'intégrité des données d'origine.

L'exception des tranches littérales

Le comportement particulier observé avec les tranches créées à partir de boucles ne s'étend pas aux tranches initialisées à partir de littéraux. Cela est dû au fait que Go alloue un nouveau tableau si une opération d'ajout dépasse la capacité du tableau de sauvegarde. Ce comportement est indépendant du fait que la tranche soit créée à partir d'un littéral ou d'une variable et est simplement une conséquence de la façon dont les tableaux sont gérés en interne dans Go.

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!

source:php.cn
Déclaration de ce site Web
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
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal