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.
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
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) } }
................................................................. ............... .................................... ..
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) } }
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!