Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Menulis ke hirisan melalui saluran dan goroutin: mengapa hirisan berakhir kosong

Menulis ke hirisan melalui saluran dan goroutin: mengapa hirisan berakhir kosong

王林
王林ke hadapan
2024-02-11 18:50:081213semak imbas

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

editor php Yuzai mendedahkan soalan tentang menghiris untuk anda: Mengapakah menulis pada bahagian melalui saluran dan goroutine akhirnya menjadi kosong? Dalam Go, saluran dan goroutin ialah alat penting untuk pengaturcaraan serentak, tetapi dalam beberapa kes, menggunakannya untuk menulis kepingan boleh menghasilkan hasil yang tidak dijangka. Artikel ini akan menerangkan punca masalah ini secara terperinci dan menyediakan penyelesaian untuk membantu anda memahami dan menangani situasi ini dengan lebih baik.

Kandungan soalan

Saya menjalankan fungsi ini:

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

Tetapi akhirnya, kepingan vertices saya kosong:

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

}

Fungsi yang kembali writer adalah seperti ini:

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
}

Bolehkah sesiapa membantu saya mengetahui mengapa vertices kepingan saya habis?

Log

Log menunjukkan bahawa vertices 切片实际上已填充。但由于某种原因,传递给doublecheckvertices kepingan itu sebenarnya telah diisi. Tetapi atas sebab tertentu, ia kosong apabila dihantar ke doublecheckvertices.

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

Penyelesaian

Ini kelihatan serupa dengan "lulus hirisan sebagai hujah fungsi dan ubah suai hirisan asal"

Jika anda mahu goroutine mengubah suai hirisan yang anda buat secara luaran, anda memerlukan penunjuk ke hirisan:

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
}

Atas ialah kandungan terperinci Menulis ke hirisan melalui saluran dan goroutin: mengapa hirisan berakhir kosong. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam