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) } }
以上是如何在错误时停止从通道读取?的详细内容。更多信息请关注PHP中文网其他相关文章!