Bagaimana untuk berhenti membaca dari saluran atas kesilapan?

WBOY
Lepaskan: 2024-02-09 14:00:11
ke hadapan
673 orang telah melayarinya

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
Salin selepas log masuk
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)
    }
}
Salin selepas log masuk

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

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)
    }
}
Salin selepas log masuk

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!

Label berkaitan:
sumber:stackoverflow.com
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan
Tentang kita Penafian Sitemap
Laman web PHP Cina:Latihan PHP dalam talian kebajikan awam,Bantu pelajar PHP berkembang dengan cepat!