Maison > développement back-end > Golang > Comment arrêter la lecture du canal en cas d'erreur ?

Comment arrêter la lecture du canal en cas d'erreur ?

WBOY
Libérer: 2024-02-09 14:00:11
avant
719 Les gens l'ont consulté

Comment arrêter la lecture du canal en cas derreur ?

L'éditeur PHP Zimo vous présentera comment arrêter la lecture de la chaîne lorsqu'une erreur se produit. Lors de l'exécution d'une opération de lecture de canal, vous rencontrez parfois une condition d'erreur, telle que la fermeture du canal ou l'expiration du délai de lecture. Afin de garantir la stabilité et la fiabilité du programme, nous devons arrêter l'opération de lecture à temps lorsque ces erreurs se produisent. Ceci peut être réalisé en configurant un gestionnaire d'erreurs ou en utilisant un mécanisme de gestion des exceptions. Après avoir détecté l'erreur, l'opération de lecture sera immédiatement terminée et la gestion des erreurs correspondante sera effectuée. Cela peut efficacement éviter les situations anormales causées par des erreurs dans le programme et améliorer la robustesse et la maintenabilité du code.

Contenu de la question

Je souhaite arrêter la lecture de la chaîne une fois qu'une erreur est rencontrée. Je pense que je dois utiliser errroup.WithContext() mais je n'arrive pas à comprendre comment l'intégrer.

Voici le résultat :

Thread 2: STARTED
Thread 1: STARTED
Thread 0: STARTED
Thread 2: GOT=0
Thread 1: GOT=1
Thread 0: GOT=2
Thread 0: FAILED
Thread 1: GOT=3
Thread 2: GOT=4
Thread 2: GOT=5
Thread 1: GOT=6
Thread 1: GOT=7
Thread 2: GOT=8
panic: Thread 0: FAILED
Copier après la connexion
package main

import (
    "fmt"
    "time"

    "golang.org/x/sync/errgroup"
)

func main() {
    const threads = 3

    ch := make(chan int, threads)

    eg := errgroup.Group{}

    for i := 0; i < threads; i++ {
        i := i
        eg.Go(func() error {
            fmt.Printf("Thread %d: STARTED\n", i)
            for n := range ch {
                fmt.Printf("Thread %d: GOT=%d\n", i, n)
                time.Sleep(time.Duration(1) * time.Second)
                // Simulate failed thread
                if n == 2 {
                    fmt.Printf("Thread %d: FAILED\n", i)
                    return fmt.Errorf("Thread %d: FAILED", i)
                }
            }
            return nil
        })
    }

    for i := 0; i < 9; i++ {
        ch <- i
    }

    close(ch)

    if err := eg.Wait(); err != nil {
        panic(err)
    }
}
Copier après la connexion

................................................................. ............... .................................... ..

Solution

errroup.WithContext() Probablement la meilleure façon (comme vous l'avez deviné). Cette réponse vaut la peine d'être lue ; elle fournit une explication complète (que je n'essaierai pas de copier !).

Cependant, comme cela peut être difficile à comprendre, voici une solution utilisant votre code (playground ) :

package main

import (
    "context"
    "fmt"
    "time"

    "golang.org/x/sync/errgroup"
)

func main() {
    const threads = 3

    ch := make(chan int, threads)

    eg, ctx := errgroup.WithContext(context.Background())
    for i := 0; i < threads; i++ {
        i := i
        eg.Go(func() error {
            fmt.Printf("Thread %d: STARTED\n", i)
            for n := range ch {
                fmt.Printf("Thread %d: GOT=%d\n", i, n)
                time.Sleep(time.Duration(1) * time.Second)
                // Simulate failed thread
                if n == 2 {
                    fmt.Printf("Thread %d: FAILED\n", i)
                    return fmt.Errorf("Thread %d: FAILED", i)
                }
                // For the purpose of this example we will just check the context after
                // doing the work.
                if ctx.Err() != nil {
                    fmt.Printf("Thread %d: Quiting due to context\n", i)
                    return fmt.Errorf("Thread %d: Context cancelled: ", i)
                }
            }
            return nil
        })
    }

    // We want to stop sending new work if there is a failure (otherwise `ch <- i` will block permanently);
sendLoop:
    for i := 0; i < 9; i++ {
        select {
        case ch <- i:
        case <-ctx.Done():
            fmt.Printf("stopped\n")
            break sendLoop // Just exit the loop if something goes wrong (you may want to do something else here)
        }
    }
    close(ch) // Note: Important that this happens even if there is an error (otherwise `for n := range ch` may block, leaking goroutines)
    fmt.Printf("all sent\n")
    if err := eg.Wait(); err != nil {
        panic(err)
    }
}
Copier après la connexion

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!

Étiquettes associées:
source:stackoverflow.com
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
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal