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>
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>
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>
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!