Rumah >pembangunan bahagian belakang >Golang >Bagaimana untuk berhenti membaca dari saluran atas kesilapan?

Bagaimana untuk berhenti membaca dari saluran atas kesilapan?

WBOY
WBOYke hadapan
2024-02-09 14:00:11716semak imbas

Bagaimana untuk berhenti membaca dari saluran atas kesilapan?

Editor PHP Zimo akan memperkenalkan anda cara berhenti membaca daripada saluran apabila ralat berlaku. Semasa menjalankan operasi bacaan saluran, anda kadangkala menghadapi keadaan ralat, seperti saluran ditutup atau tamat masa bacaan. Untuk memastikan kestabilan dan kebolehpercayaan program, kami perlu menghentikan operasi baca dalam masa apabila ralat ini berlaku. Ini boleh dicapai dengan menyediakan pengendali ralat atau menggunakan mekanisme pengendalian pengecualian Selepas menangkap ralat, operasi baca akan ditamatkan serta-merta dan pengendalian ralat yang sepadan akan dilakukan. Ini dengan berkesan boleh mengelakkan situasi tidak normal yang disebabkan oleh ralat dalam program dan meningkatkan keteguhan dan kebolehselenggaraan kod.

Kandungan soalan

Saya mahu berhenti membaca dari saluran apabila ralat ditemui. Saya rasa saya perlu menggunakan errroup.WithContext() tetapi saya tidak begitu memahami cara mengintegrasikannya.

Ini adalah output:

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

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

Penyelesaian

errroup.WithContext() Mungkin cara terbaik (seperti yang anda sangka). Jawapan ini patut dibaca; ia memberikan penjelasan yang komprehensif (yang saya tidak akan cuba salin!).

Namun, memandangkan ini mungkin sukar difahami, berikut ialah penyelesaian menggunakan kod anda (taman permainan ):

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

Atas ialah kandungan terperinci Bagaimana untuk berhenti membaca dari saluran atas kesilapan?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam