Maison >développement back-end >Golang >Pouvez-vous sélectionner les canaux d'envoi et de réception dans Go, sans blocage ?

Pouvez-vous sélectionner les canaux d'envoi et de réception dans Go, sans blocage ?

Susan Sarandon
Susan Sarandonoriginal
2024-10-26 22:34:31952parcourir

 Can You Select on Both Sending and Receiving Channels in Go, Without Blocking?

Sélection des canaux bidirectionnels pour l'envoi et la réception conditionnels

Dans Go, il est possible de configurer des canaux mis en mémoire tampon pour l'envoi et la réception, permettant opérations sélectives en fonction de leur disponibilité. Considérons le scénario suivant :

<code class="go">s := make(chan<- int, 5)
r := make(<-chan int)

Nous avons un canal d'envoi tamponné s et un canal de réception non tamponné r. La question se pose : peut-on sélectionner sur les deux canaux pour déterminer si r contient des données ou si s n'est pas plein ? Cela imite les fonctionnalités suivantes, mais sans consommer 100 % du processeur :

<code class="go">for {
    if len(s) < cap(s) {
        // Send something
    }
    if len(r) > 0 {
        // Receive something
    }
}</code>

Implémentation de Select avec un cas par défaut

Pour y parvenir, nous pouvons utiliser le instruction select avec un cas par défaut. Dans le cas par défaut, si aucun des deux canaux n'est prêt, nous « mettons en veille » temporairement la goroutine pour éviter une consommation inutile de ressources.

<code class="go">s := make(chan<- int, 5)
r := make(<-chan int)

for {
    v := valueToSend() // Value to be sent, evaluated upon each attempt
    select {
    case s <- v:
        fmt.Println("Sent value:", v)
    case vr := <-r:
        fmt.Println("Received:", vr)
    default: // Neither channel is ready, pause briefly
        time.Sleep(time.Millisecond * 1)
    }
}

Pourquoi les contrôles de longueur et de capacité ne sont pas idéaux

Il est crucial d'éviter de vérifier la longueur ou la capacité d'un canal avant de tenter d'envoyer ou de recevoir. En effet, l'état du canal peut changer entre le moment de la vérification et le fonctionnement réel, conduisant potentiellement à un blocage inattendu. Par exemple :

<code class="go">if len(r) > 0 {
    // r is ready to receive

    // Other code...

    r <-  // This may block if another goroutine has already received from r!
}</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:
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