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

王林
Lepaskan: 2024-02-11 18:50:08
ke hadapan
1238 orang telah melayarinya

通过通道和 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)
}
Salin selepas log masuk

Tetapi akhirnya, kepingan vertices saya kosong:

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

}
Salin selepas log masuk

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
}
Salin selepas log masuk

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))
Salin selepas log masuk

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
}
Salin selepas log masuk

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!

Label berkaitan:
sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!