Maison > développement back-end > Golang > Pourquoi `append()` de Golang semble-t-il modifier une tranche après son envoi sur un canal ?

Pourquoi `append()` de Golang semble-t-il modifier une tranche après son envoi sur un canal ?

Linda Hamilton
Libérer: 2024-11-02 10:01:31
original
350 Les gens l'ont consulté

Why Does Golang's `append()` Seem to Modify a Slice After It's Sent Over a Channel?

Quand Golang append() crée-t-il une nouvelle tranche ?

La documentation pour append() indique qu'il allouera une nouvelle tranche et copier les éléments lorsque la capacité de la tranche d'origine est insuffisante. Cependant, une divergence survient lors de l'examen de la sortie du code suivant, qui génère des combinaisons d'un alphabet booléen.

<code class="go">package main

import (
    "fmt"
)

func AddOption(c chan []bool, combo []bool, length int) {
    if length == 0 {
        fmt.Println(combo, "!")
        c <- combo
        return
    }
    var newCombo []bool
    for _, ch := range []bool{true, false} {
        newCombo = append(combo, ch)
        AddOption(c, newCombo, length-1)
    }
}

func main() {
    c := make(chan []bool)
    go func(c chan []bool) {
        defer close(c)
        AddOption(c, []bool{}, 4)
    }(c)
    for combination := range c {
        fmt.Println(combination)
    }
}</code>
Copier après la connexion

Observations contrastées

Dans la sortie, le les lignes se terminant par un point d'exclamation représentent les tranches envoyées sur le canal par AddOption, tandis que les lignes sans point d'exclamation montrent les tranches reçues dans main(). Il est à noter que les tranches envoyées sur le canal semblent avoir été modifiées après avoir été envoyées, bien que append() aurait renvoyé une nouvelle tranche.

Examen de la source

Le bloc de code douteux is :

<code class="go">var newCombo []bool
for _, ch := range []bool{true, false} {
    newCombo = append(combo, ch)
    AddOption(c, newCombo, length-1)
}</code>
Copier après la connexion

Selon la documentation, append() devrait renvoyer un nouveau descripteur de tranche pointant vers un nouveau tableau de données sous-jacent lorsque la capacité de la tranche d'origine n'est pas suffisante. Cependant, la valeur transmise comme deuxième argument à AddOption peut être soit un pointeur vers un descripteur de tranche, soit une copie authentique du descripteur de tranche.

Clarification du comportement

La réponse à cette question réside dans la distinction entre le type de données slice et sa représentation réelle. Un descripteur de tranche se compose de deux entiers pour la longueur et la capacité, ainsi que d'un pointeur vers les données sous-jacentes.

Bien que append() renvoie un nouveau descripteur de tranche avec un tableau de données sous-jacent potentiellement différent, le pointeur vers les données reste la même à moins que la capacité soit augmentée. Cela signifie que même si le descripteur de tranche lui-même est une copie, la valeur du pointeur (adresse des données sous-jacentes) est partagée.

Exemple supplémentaire

À titre d'illustration, considérons ceci extrait de code :

<code class="go">package main

import "fmt"

func main() {
    s := make([]int, 0, 5)
    s = append(s, []int{1, 2, 3, 4}...)

    a := append(s, 5)
    fmt.Println(a)

    b := append(s, 6)
    fmt.Println(b)
    fmt.Println(a)
}</code>
Copier après la connexion

Ce code s'imprime :

[1 2 3 4 5]
[1 2 3 4 6]
[1 2 3 4 6]
Copier après la connexion

Initialement, s a suffisamment de capacité, donc a et b partagent le même pointeur de données sous-jacent. Cependant, si nous réduisons la capacité de s à 4, le résultat devient :

[1 2 3 4 5]
[1 2 3 4 6]
[1 2 3 4 5]
Copier après la connexion

Cela démontre que a et b ne partagent les mêmes données sous-jacentes que lorsque s a une capacité suffisante.

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