Rumah  >  Artikel  >  pembangunan bahagian belakang  >  goroutine penerima tidak pernah menghalang apabila golang menutup saluran

goroutine penerima tidak pernah menghalang apabila golang menutup saluran

王林
王林ke hadapan
2024-02-06 08:25:071212semak imbas

goroutine penerima tidak pernah menghalang apabila golang menutup saluran

Kandungan soalan

Saya menulis beberapa kod untuk mempelajari saluran go, sekeping kod seperti yang ditunjukkan di bawah:

func main(){
    intChan := make(chan int, 1)
    strChan := make(chan string, 1)

    intChan <- 3
    strChan <- "hello"
    fmt.Println("send")

    // comment this, fatal error: all goroutines are asleep - deadlock!
    // close(intChan)
    // close(strChan)

    for {
        select {
        case e, ok := <-intChan:
            time.Sleep(time.Second * 2)
            fmt.Println("The case intChan ok: ", ok)
            fmt.Println("The case intChan is selected.", e)

        case e, ok := <-strChan:
            time.Sleep(time.Second)
            fmt.Println("The case strChan ok: ", ok)
            fmt.Println("The case strChan is selected.", e)
        }
    }
}

Jika saya mengulas fungsi close(), pernyataan "untuk" akan menyekat, kerana ralat mengatakan "semua goroutine sedang tidur - kebuntuan!", yang nampaknya munasabah.

Jika saya membatalkan komen close(), kenyataan "untuk" tidak pernah berhenti. Penerima mendapat nilai lalai 0 dan nol dari saluran dan tidak pernah menyekat.

Walaupun saya tidak menghantar apa-apa ke saluran dan menelefon close() selepas menentukan saluran. Penerima tidak akan menyekat atau menyebabkan sebarang ralat.

Saya keliru tentang fungsi close, adakah ia memulakan rutin pergi yang menghantar jenis nilai lalai tertentu ke saluran dan tidak pernah berhenti? close 函数的作用感到困惑,它是否启动一个 go 例程将特定类型的默认值发送到通道,并且永远不会停止?


正确答案


当频道关闭时,您仍然可以阅读它,但您的 ok 将为 false。所以,这就是为什么你的 for 永远不会停止。并且,您需要通过条件 if !ok {break } 来中断 for

Jawapan betul

Apabila saluran ditutup, anda masih boleh membacanya, tetapi ok anda adalah palsu. Jadi, itulah sebabnya for anda tidak pernah berhenti. Selain itu, anda perlu memecahkan pernyataan for dengan if !ok {break } bersyarat.

make(chan int, 1)Apabila saluran tidak ditutup, apabila anda cuba membaca data daripadanya, ia akan disekat atau tidak, bergantung kepada saluran buffer/tidak buffer.
make(chan int)Saluran penimbal: Anda nyatakan saiz (

).

Saluran tidak buffer: Anda tidak memberikan saiz (close 的情况下,它将从您缓冲的通道读取数据一次,因为您通过 intchan 和 <code>strchan )

Dalam ulasan anda

Hantar data ke saluran. Oleh itu, anda akan melihat hasil berikut yang dicetak oleh konsol.

send
the case strchan ok:  true
the case strchan is selected. hello
the case intchan ok:  true
the case intchan is selected. 3
all goroutine are sleep - deadlockNamun, selepas ini, kedua-dua saluran penimbal tidak lagi mempunyai data. Kemudian jika anda cuba membacanya anda akan disekat kerana tiada data dalam saluran buffer. (Malah, tiada penimbalan juga berlaku apabila tiada data.)

Kemudian, anda mendapat

kerana goroutine utama disekat menunggu data daripada saluran. Dengan cara ini, apabila anda menjalankan program ini, ia memulakan goroutine utama untuk menjalankan kod anda. Jika hanya satu goroutine utama disekat, ini bermakna tiada siapa yang boleh membantu anda menjalankan kod anda.

Anda boleh menambah kod berikut sebelum pernyataan for. 🎜
go func() {
    fmt.Println("another goroutine")
    for {}
}()
🎜Anda akan mendapati bahawa anda tidak menemui jalan buntu kerana masih terdapat goroutine yang "mungkin" menjalankan kod anda. 🎜

Atas ialah kandungan terperinci goroutine penerima tidak pernah menghalang apabila golang menutup saluran. 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