Maison  >  Article  >  développement back-end  >  Écrire dans des tranches via des canaux et des goroutines : pourquoi les tranches finissent vides

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

王林
王林avant
2024-02-11 18:50:081211parcourir

通过通道和 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)
}

Mais au final, ma vertices tranche est vide :

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

}

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
}

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

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
}

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:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer