Maison > développement back-end > Golang > Comment puis-je hiérarchiser les canaux dans l'instruction « select » de Go ?

Comment puis-je hiérarchiser les canaux dans l'instruction « select » de Go ?

Patricia Arquette
Libérer: 2024-12-03 03:18:13
original
375 Les gens l'ont consulté

How Can I Prioritize Channels in Go's `select` Statement?

Priorité dans l'instruction Go Select

Lorsque vous travaillez avec plusieurs canaux à l'aide de l'instruction select de Go, l'ordre dans lequel les canaux sont traités n'est pas garanti. Pour donner la priorité à un canal par rapport à un autre, une solution de contournement est disponible.

Énoncé du problème

Dans l'extrait de code ci-dessous, l'objectif est de garantir que toutes les valeurs du canal de sortie sont traités avant le canal de sortie :

package main

import "fmt"

func sender(out chan int, exit chan bool){
    for i := 1; i <= 10; i++ {
        out <- i
    }
    exit <- true
}

func main(){
    out := make(chan int, 10)
    exit := make(chan bool)

    go sender(out, exit)

    L:
    for {
        select {
            case i := <-out:
                fmt.Printf("Value: %d\n", i)
            case <-exit:
                fmt.Println("Exiting")
                break L
        }
    }
    fmt.Println("Did we get all 10? Most likely not")
}
Copier après la connexion

Cependant, l'utilisation de l'instruction select ne donne pas la priorité à un canal sur le autre.

Solution : prise en charge de la langue native

Go prend en charge nativement la priorisation des chaînes dans une instruction select en limitant la visibilité de la chaîne « quitter » au seul producteur. Lorsque le producteur décide de démissionner, il ferme la chaîne. Le consommateur ne quittera que lorsque le canal sera vide et fermé.

package main

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

var (
    produced  = 0
    processed = 0
)

func produceEndlessly(out chan int, quit chan bool) {
    defer close(out)
    for {
        select {
        case <-quit:
            fmt.Println("RECV QUIT")
            return
        default:
            out <- rand.Int()
            time.Sleep(time.Duration(rand.Int63n(5e6)))
            produced++
        }
    }
}

func quitRandomly(quit chan bool) {
    d := time.Duration(rand.Int63n(5e9))
    fmt.Println("SLEEP", d)
    time.Sleep(d)
    fmt.Println("SEND QUIT")
    quit <- true
}

func main() {
    vals, quit := make(chan int, 10), make(chan bool)
    go produceEndlessly(vals, quit)
    go quitRandomly(quit)
    for x := range vals {
        fmt.Println(x)
        processed++
        time.Sleep(time.Duration(rand.Int63n(5e8)))
    }
    fmt.Println("Produced:", produced)
    fmt.Println("Processed:", processed)
}
Copier après la connexion

Dans cet exemple, le canal de sortie n'est visible que par la fonction producteur (produceEndlessly). Le producteur décide d'arrêter, au hasard, après un certain délai. La fonction consommateur (principale) parcourt le canal vals jusqu'à ce qu'il soit fermé et vide. En donnant la priorité au message « quitter » du producteur, toutes les valeurs du canal vals sont traitées avant la fin du programme.

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!

source:php.cn
Déclaration de ce site Web
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
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal