Maison > développement back-end > Golang > le corps du texte

Écrire dans des tranches via des canaux et des goroutines : pourquoi les tranches finissent vides

王林
Libérer: 2024-02-11 18:50:08
avant
1237 Les gens l'ont consulté

通过通道和 goroutine 写入切片:为什么切片最终为空

L'éditeur php Yuzai révèle pour vous une question sur le découpage : pourquoi l'écriture dans le slice via les canaux et goroutine finit-elle par être vide ? Dans Go, les canaux et les goroutines sont des outils importants pour la programmation simultanée, mais dans certains cas, leur utilisation pour écrire des tranches peut avoir des résultats inattendus. Cet article expliquera en détail la cause de ce problème et proposera des solutions pour vous aider à mieux comprendre et gérer cette situation.

Contenu de la question

J'exécute cette fonction :

func run() () {
    // this slice is going to be filled out by a channel and goroutine.
    vertices := make([]vertex, 0)

    var wg sync.waitgroup

    // obtain a writer to fill out the vertices.
    writer := writer(&wg, vertices)

    // run an arbitrary logic to send data to writer.
    logic(writer)

    // stop the writer reading on the channel.
    close(writer)

    // wait for the write to complete.
    wg.wait()

    // see if vertices slice is actually filled out.
    doublecheckvertices(vertices)
}
Copier après la connexion

Mais au final, ma vertices tranche est vide :

func doublecheckvertices(vertices []vertex) () {
    // here i notice that `vertices` slice is actually empty :(

}
Copier après la connexion

La fonction qui renvoie writer est comme ceci :

func writer(wg *sync.waitgroup, vertices []vertex) (chan<- []*triangle3) {
    // external code writes to this channel.
    // this goroutine reads the channel and writes to vertices.
    writer := make(chan []*triangle3)

    // write by a goroutine.
    wg.add(1)
    go func() {
        defer wg.done()

        a := vertex{}

        // read from the channel and write them to vertices.
        for ts := range writer {
            for _, t := range ts {
                a.x = float32(t.v[0].x)
                a.y = float32(t.v[0].y)
                a.z = float32(t.v[0].z)
                vertices = append(vertices, a)
            }
        }
    }()

    return writer
}
Copier après la connexion

Quelqu'un peut-il m'aider à comprendre pourquoi ma vertices tranche finit vide ?

Journal

Le journal montre que vertices 切片实际上已填充。但由于某种原因,传递给doublecheckvertices la tranche est effectivement remplie. Mais pour une raison quelconque, il est vide lorsqu'il est transmis à doublecheckvertices.

                vertices = append(vertices, a)
                // This Log shows the slice is actually filled out:
                fmt.Printf("vertices len() is %v\n", len(vertices))
Copier après la connexion

Solution de contournement

Cela ressemble à "passer la tranche comme argument de fonction et modifier la tranche d'origine"

Si vous souhaitez que la goroutine modifie une tranche que vous avez créée en externe, vous avez besoin d'un pointeur vers la tranche :

func Writer(wg *sync.WaitGroup, vertices *[]Vertex) (chan<- []*Triangle3) {
    // External code writes to this channel.
    // This goroutine reads the channel and writes to vertices.
    writer := make(chan []*Triangle3)

    // Write by a goroutine.
    wg.Add(1)
    go func() {
        defer wg.Done()

        a := Vertex{}

        // Read from the channel and write them to vertices.
        for ts := range writer {
            for _, t := range ts {
                a.X = float32(t.V[0].X)
                a.Y = float32(t.V[0].Y)
                a.Z = float32(t.V[0].Z)
                *vertices = append(*vertices, a)  <=====
            }
        }
    }()

    return writer
}
Copier après la connexion

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!

Étiquettes associées:
source:stackoverflow.com
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!