web-dev-qa-db-fra.com

Golang - Comment savoir qu'un canal en mémoire tampon est plein

Comment savoir qu'un canal en mémoire tampon est plein? Je ne sais pas être bloqué lorsque le canal en mémoire tampon est plein, mais j'ai choisi de supprimer l'élément envoyé au canal en mémoire tampon.

34
GarudaReiga

Vous pouvez utiliser select instruction avec une valeur par défaut. Dans le cas où il n'est pas possible de faire l'un des cas, comme l'envoi à un canal complet, l'instruction fera la valeur par défaut:

package main

import "fmt"

func main() {
    ch := make(chan int, 1)

    // Fill it up
    ch <- 1

    select {
    case ch <- 2: // Put 2 in the channel unless it is full
    default:
        fmt.Println("Channel full. Discarding value")
    }
}

Sortie:

Canal plein. Jeter la valeur

Aire de jeux: http://play.golang.org/p/1QOLbj2Kz2

Vérifier sans envoyer

Il est également possible de vérifier le nombre d'éléments mis en file d'attente dans un canal en utilisant len(ch), comme indiqué dans Go spécifications . Ceci en combinaison avec cap nous permet de vérifier si un canal est plein sans envoyer de données.

if len(ch) == cap(ch) {
    // Channel was full, but might not be by now
} else {
    // Channel wasn't full, but might be by now
}

Notez que le résultat de la comparaison peut être invalide au moment où vous entrez le bloc if

86
ANisus

au lieu de cela, je choisis de supprimer l'élément envoyé sur le canal en mémoire tampon.

Cela s'appelle "canal débordant", et vous trouvez la réponse d'ANisus implémentée dans eapache/channels/overflowing_channel.go :

for elem := range ch.input {
    // if we can't write it immediately, drop it and move on
    select {
    case ch.output <- elem:
    default:
    }
}
close(ch.output)

Mais ce projet eapache/canaux implémente également d'autres stratégies:

  • OverflowingChannel implémente l'interface Channel d'une manière qui ne bloque jamais l'écrivain.
    Plus précisément, si une valeur est écrite dans un OverflowingChannel lorsque son tampon est plein
    (ou, dans un cas non tamponné, lorsque le destinataire n'est pas prêt), cette valeur est simplement supprimée.

Pour le comportement opposé (éliminer l'élément le plus ancien, pas le plus récent), voir RingChannel.

11
VonC

Un autre exemple utile sur lequel je suis tombé était cette implémentation astucieuse of Ring Buffer .

La citation de la source:

L'idée est simple: connectez deux canaux tamponnés via un Goroutine qui transmet les messages du canal entrant au canal sortant. Chaque fois qu'un nouveau message ne peut pas être placé sur le canal sortant, retirez un message du canal sortant (c'est-à-dire le plus ancien message du tampon), supprimez-le et placez le nouveau message dans le canal sortant nouvellement libéré.

Découvrez cette version C ainsi ...

1
Ostati