Maison  >  Article  >  développement back-end  >  le canal Golang n'est pas fermé

le canal Golang n'est pas fermé

PHPz
PHPzoriginal
2023-05-15 12:29:36519parcourir

Dans Golang, le canal est une structure de données très utile qui peut transmettre des données en toute sécurité entre les coroutines. Un canal peut être fermé pour informer le récepteur que toutes les données ont été transmises. Cependant, dans certains cas, ne pas fermer la chaîne peut être une meilleure option.

Tout d'abord, voyons pourquoi la fermeture d'une chaîne pourrait aider. Lorsque nous envoyons des données à un canal, elles peuvent être écoutées par plusieurs coroutines en même temps. Nous avons ici un exemple simple :

c := make(chan int)
go func() {
    for i := 0; i < 10; i++ {
        c <- i
    }
}()

go func() {
    for i := range c {
        fmt.Println(i)
    }
}()

Ici, nous créons un canal de type entier et démarrons deux coroutines. Une coroutine envoie les nombres 0 à 9 au canal, tandis que l'autre coroutine imprime les données une fois qu'elle les reçoit.

Lorsque l'expéditeur a terminé l'envoi, il doit fermer le canal afin que le destinataire sache que toutes les données ont été transmises. Cela peut être accompli en appelant close(c) lorsque la coroutine d'envoi a terminé l'envoi. close(c)来完成。

但是,如果某个协程可能无法接收到所有的数据怎么办?也许它已经挂起或已经关闭了。在这种情况下,发送方关闭通道可能会引起接收方的panic,从而导致程序崩溃。

解决这个问题的方法可能是在发送方增加一个锁,并在接收方的协程完成时释放它。但这种方法可能会使我们的代码变得更加复杂,并且可能降低性能。

还有一个更好的方法,这就是不关闭通道,而是利用Go语言的特性,在通道上发送额外的元素来指示所有的数据都已发送。这个元素可以是任何类型,通常情况下我们使用nil或者一个特定的标记。

以下是如何对我们的示例代码进行修改:

c := make(chan int)
done := make(chan struct{})
go func() {
    for i := 0; i < 10; i++ {
        c <- i
    }
    done <- struct{}{}
}()

go func() {
    for {
        select {
        case i := <-c:
            fmt.Println(i)
        case <-done:
            return
        }
    }
}()

在这里,我们创建了一个通道done,并在发送方完成发送时向其中发送了一个结构体。接收方的协程使用了select语句来监听两个通道。一旦接收到了来自通道done

Mais que se passe-t-il si une coroutine ne reçoit pas toutes les données ? Peut-être qu'il est accroché ou fermé. Dans ce cas, la fermeture du canal par l'expéditeur peut provoquer une panique du destinataire, provoquant le crash du programme.

Une solution à ce problème pourrait être d'ajouter un verrou sur l'expéditeur et de le libérer lorsque la coroutine du destinataire est terminée. Mais cette approche peut rendre notre code plus complexe et réduire les performances. #🎜🎜##🎜🎜# Il existe un meilleur moyen, qui n'est pas de fermer la chaîne, mais d'utiliser les fonctionnalités du langage Go pour envoyer des éléments supplémentaires sur la chaîne pour indiquer que toutes les données ont été envoyées. Cet élément peut être de n'importe quel type, nous utilisons généralement nil ou une balise spécifique. #🎜🎜##🎜🎜#Voici comment modifier notre exemple de code : #🎜🎜#rrreee#🎜🎜#Ici on crée un canal done et on le complète côté expéditeur Une structure est envoyée à lors de l'envoi. La coroutine du récepteur utilise l'instruction select pour écouter deux canaux. Une fois qu'il reçoit un signal du canal done, il quitte. Cela évite le problème de la fermeture du canal tout en offrant un moyen simple d'indiquer au récepteur que toutes les données ont été envoyées. #🎜🎜##🎜🎜# En résumé, la fermeture de la chaîne peut causer des problèmes inutiles car cela peut provoquer le crash du programme. Dans certains cas, ne pas fermer la chaîne peut être une meilleure option. Nous pouvons envoyer des éléments supplémentaires sur le canal pour indiquer que toutes les données ont été envoyées. Cette approche évite le besoin de verrous et rend le programme plus simple et plus efficace. #🎜🎜#

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:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Article précédent:langage c vers golangArticle suivant:langage c vers golang