Maison >développement back-end >Golang >La goroutine du récepteur ne se bloque jamais lorsque Golang ferme le canal

La goroutine du récepteur ne se bloque jamais lorsque Golang ferme le canal

王林
王林avant
2024-02-06 08:25:071241parcourir

La goroutine du récepteur ne se bloque jamais lorsque Golang ferme le canal

Contenu de la question

J'ai écrit du code pour apprendre le canal Go, un morceau de code comme indiqué ci-dessous :

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

Si je commente la fonction close(), l'instruction "for" bloquera, car l'erreur dit "toutes les goroutines sont en veille - impasse !", ce qui semble raisonnable.

Si je décommente close(), la déclaration "pour" ne s'arrête jamais. Le récepteur obtient les valeurs par défaut 0 et zéro du canal et ne bloque jamais.

Même si je n'envoie rien à la chaîne et que j'appelle close() après avoir défini la chaîne. Le récepteur ne bloquera jamais ni ne provoquera d'erreurs.

Je ne comprends pas ce que fait la fonction close, démarre-t-elle une routine go qui envoie un type spécifique de valeur par défaut au canal et ne s'arrête jamais ? close 函数的作用感到困惑,它是否启动一个 go 例程将特定类型的默认值发送到通道,并且永远不会停止?


正确答案


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

Bonne réponse

Lorsque la chaîne est fermée, vous pouvez toujours la lire, mais votre ok sera faux. C'est pourquoi votre for ne s'arrête jamais. De plus, vous devez interrompre l'instruction for avec un conditionnel if !ok {break }.

make(chan int, 1)Lorsque le canal n'est pas fermé, lorsque vous essayez d'en lire des données, il sera bloqué ou non, selon le canal tamponné/non tamponné.
make(chan int)Canal tampon : Vous spécifiez la taille (

).

Chaîne sans tampon : Vous n'avez pas donné de taille (close 的情况下,它将从您缓冲的通道读取数据一次,因为您通过 intchan 和 <code>strchan )

Dans votre commentaire

Envoyez des données à la chaîne. Par conséquent, vous verrez les résultats suivants imprimés par la console.

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 - deadlockCependant, après cela, les deux canaux tampons ne contiennent plus de données. Ensuite, si vous essayez de le lire, vous serez bloqué car il n'y a aucune donnée dans le canal mis en mémoire tampon. (En fait, l'absence de mise en mémoire tampon est également le cas lorsqu'il n'y a pas de données.)

Ensuite, vous obtenez

car la goroutine principale est bloquée en attendant les données du canal. À propos, lorsque vous exécutez ce programme, il démarre une goroutine principale pour exécuter votre code. Si un seul goroutine principal est bloqué, cela signifie que personne ne peut vous aider à exécuter votre code.

Vous pouvez ajouter le code suivant avant l'instruction for. 🎜
go func() {
    fmt.Println("another goroutine")
    for {}
}()
🎜Vous constaterez que vous ne rencontrez pas de blocage car il existe toujours une goroutine qui "pourrait" exécuter votre code. 🎜

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