Question canal de vidange périodique au golang


J'ai besoin de vider périodiquement le contenu d'un canal. Je l'ai fait avec len () et je me demande s'il existe une meilleure façon de le faire.

http://play.golang.org/p/YzaI_2c_-F

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    commch := make(chan int, 100)
    go fillchan(commch)
    drainchan(commch)
}

func fillchan(commch chan int) {
    for {
        select {
        case <-time.Tick(30 * time.Millisecond):
            commch <- rand.Int()
        }
    }
}

func drainchan(commch chan int) {
    for {
        chanlen := len(commch) // get number of entries in channel
        time.Sleep(1 * time.Second)
        for i := 0; i <= chanlen; i++ { //flush them based on chanlen
            fmt.Printf("chan len: %s num: %s\n", chanlen, <-commch)
        }
    }
}

EDIT 1: semble être la meilleure façon de le faire http://play.golang.org/p/4Kp8VwO4yl

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    commch := make(chan int, 1000)
    go fillchan(commch)
    for {
        select {
        case <-time.Tick(1000 * time.Millisecond):
            drainchan(commch)
        }
    }
}

func fillchan(commch chan int) {
    for {
        select {
        case <-time.Tick(300 * time.Millisecond):
            commch <- rand.Int()
        }
    }
}

func drainchan(commch chan int) {
    for {
        select {
        case e := <-commch:
            fmt.Printf("%s\n",e)
        default:
            return
        }
    }
}

EDIT 2: enlevé select, empêché la fuite de mémoire avec le temps. http://play.golang.org/p/WybAhRE3u4

package main

import (
    "fmt"
    "math/rand"
    "time"
)

func main() {
    commch := make(chan int, 1000)
    go fillchan(commch)
    for _ = range time.Tick(1000 * time.Millisecond) {
        drainchan(commch)
    }
}

func fillchan(commch chan int) {
    for _ = range time.Tick(300 * time.Millisecond) {
        commch <- rand.Int()
    }
}

func drainchan(commch chan int) {
    for {
        select {
        case e := <-commch:
            fmt.Printf("%s\n", e)
        default:
            return
        }
    }
}

10
2018-06-24 20:19


origine


Réponses:


La nécessité de vider le contenu d'un canal serait inhabituelle. Les canaux ne fournissent pas cette fonctionnalité - mais vous pouvez créer un goroutine qui se comportera de cette façon (... si vous vraiment ne veux pas).

En règle générale, vous penseriez plus à une goroutine qui entre sur un canal et des sorties sur un autre; les deux canaux portent le même type de données. Vous pouvez en principe modéliser tous les canaux tamponnés de cette manière; pour ses clients, le goroutine se comporte comme un canal tamponné ordinaire car il transmet ce qu'il reçoit.

Ajouter un troisième canal dans la goroutine, combiné avec un sélectionner entre elle et l'entrée. Cela vous permettra de déclencher le vidage de la mémoire tampon sans que les conditions de course ne s'introduisent. Simple.

Maintenant, il y a trois canaux connectés à la goroutine - deux entrées et une sortie. Ainsi, lorsque vous concevez les éléments qui vont l’utiliser, vous pouvez raisonner sur la sémantique du vidage de ces données.

Un relatif vient à l'esprit. Considérons un goroutine avec une entrée et un canal de sortie. Il fournit un tampon de réécriture de taille fixe, c'est-à-dire toujours prêt à être lu à partir de son canal d'entrée, même lorsque le canal de sortie est bloqué. Cela nécessitera également un sélectionner avec un cas par défaut, mais aucun troisième canal n'est nécessaire. Les tampons de réécriture ont un cas d'utilisation clair: lorsque les canaux et les goroutines sont câblés en boucles, le blocage peut être très probable. Les tampons de réécriture sont utiles en tant que solution candidate pour les blocages, car certaines données sont inutiles en retard - par exemple, vous pouvez, par exemple, jeter des événements de souris dans une interface graphique lorsque l'application est trop chargée pour y répondre.


6
2018-06-25 18:03



le BatchingChannel de https://github.com/eapache/channels fait ce que vous avez besoin je pense.


1
2018-03-12 15:11