php小编子墨为您介绍如何在错误时停止从通道读取。在进行通道读取操作时,有时会遇到错误情况,比如通道已关闭或者读取超时。为了保证程序的稳定性和可靠性,我们需要在这些错误发生时及时停止读取操作。可以通过设置错误处理程序或使用异常处理机制来实现,在捕获到错误后,立即终止读取操作,并进行相应的错误处理。这样可以有效避免程序因错误而导致的异常情况,提高代码的健壮性和可维护性。
一旦遇到错误,我想停止从通道读取。我认为我需要使用 errroup.WithContext() 但我无法完全理解如何集成它。
这是输出:
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()
可能是最好的方法(正如你所猜测的)。 这个答案值得一读;它提供了全面的解释(我不会尝试复制!)。
但是,由于这可能很难理解,这里是使用您的代码的一种解决方案(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) } }
Das obige ist der detaillierte Inhalt vonWie kann ich das Lesen des Kanals bei einem Fehler stoppen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!