Čítanie z goroutine kanál bez blokovania

0

Otázka

Mám dve goroutines: hlavná worker a helper že to zdarma off pre nejakú pomoc. helper môžu sa vyskytnúť chyby, tak používam kanál na komunikáciu chyby viac z helper na worker.

func helper(c chan <- error) (){
    //do some work
    c <- err // send errors/nil on c
}

Tu je, ako helper() sa nazýva:

func worker() error {
    //do some work
    c := make(chan error, 1)
    go helper(c)
    err := <- c
    return err
}

Otázky:

  • Je vyhlásenie err := <- c blokovanie worker? Ja myslím, že nie, pretože kanál je nárazníkový.

  • Ak je blokovanie, ako môžem, aby to non-blocking? Moja požiadavka je, aby sme sa worker a jeho volajúceho pokračovať so zvyškom práce, bez čakania na hodnotu, aby sa objaví na kanál.

Vďaka.

channel go goroutine
2021-11-24 01:59:57
3

Najlepšiu odpoveď

2

Môžete ľahko overiť

func helper(c chan<- error) {
    time.Sleep(5 * time.Second)
    c <- errors.New("") // send errors/nil on c
}

func worker() error {
    fmt.Println("do one")

    c := make(chan error, 1)
    go helper(c)

    err := <-c
    fmt.Println("do two")

    return err
}

func main() {
    worker()
}

Otázka: Je vyhlásenie err := <- c blokovanie pracovníka? Ja myslím, že nie, pretože kanál je nárazníkový.

Odpoveď: err := <- c bude blokovať pracovník.

Otázka: Ak je blokovanie, ako môžem, aby to non-blocking? Moja požiadavka je, aby robotník a jeho volajúceho pokračovať so zvyškom práce, bez čakania na hodnotu, ktorú chcete zobraziť na kanál.

Odpoveď: Ak nechcete, blokovanie, len odstrániť err := <-c. Ak potrebujete err na konci, len presunúť err := <-c do konca.

Nie je možné čítať kanál bez blokovania, ak sa vám prejsť bez blokovania, si môžete žiadne ďalšie exec tohto kódexu, pokiaľ váš kód je v slučke.

Loop:
    for {
        select {
        case <-c:
            break Loop
        default:
            //default will go through without blocking
        }
        // do something
    }

A videli ste niekedy errgroup alebo waitgroup?

To pomocou atómového, zrušiť súvislosti a synchronizácia.Raz na vykonanie tohto.

https://github.com/golang/sync/blob/master/errgroup/errgroup.go

https://github.com/golang/go/blob/master/src/sync/waitgroup.go

Alebo môžete jednoducho použiť, prejdite si func a potom čakať na chyby v akomkoľvek mieste, ktoré chcete.

2021-12-01 21:31:34
1

V kódu, zvyšok práce je nezávislé od toho, či radca sa vyskytla chyba. Môžete jednoducho získať z kanála po zvyšok práce je dokončená.

func worker() error {
    //do some work
    c := make(chan error, 1)
    go helper(c)
    //do rest of the work
    return <-c
}
2021-11-24 02:54:28

Dobre, nechcel pracovník() byť zablokované dovtedy, kým hodnota sa objaví na c?
Someone

Tiež, práve som editoval worker(). To vráti chybovú/nil na jeho volajúceho. Takže, by táto činnosť byť zablokované?
Someone

Áno, že konkrétnu prevádzku bude blokovať, kým helper odošle e error alebo nil ku kanálu. Ale pracovník je blokovaný iba po tom čo dokončil všetky jeho práce.
Chandra Sekar

Ale, že blokuje volajúceho z worker. Existuje spôsob, ako robiť to non-blocking?
Someone

Ak pracovník, a preto jeho volajúceho, nie čakať na pomocníkom na dokončenie, ako to môže vrátiť chyba z helper?
Chandra Sekar
0

Myslím si, že je potrebné tento kód..

spustiť tento kód

package main

import (
    "log"
    "sync"
)

func helper(c chan<- error) {

    for {
        var err error = nil
        // do job

        if err != nil {
            c <- err // send errors/nil on c
            break
        }
    }

}

func worker(c chan error) error {
    log.Println("first log")

    go func() {
        helper(c)
    }()

    count := 1
    Loop:
        for {
            select {
            case err := <- c :
                return err
            default:
                log.Println(count, " log")
                count++
                isFinished := false
                // do your job
                if isFinished {
                    break Loop // remove this when you test

                }
            }
        }
    return nil
}

func main() {
    wg := sync.WaitGroup{}
    wg.Add(1)
    go func() {
        c := make(chan error, 1)
        worker(c)
        wg.Done()
    }()
    wg.Wait()
}
2021-11-24 02:35:53

Môžete vysvetliť, ako upraviť na toto odpoveď, prečo by to pomohlo? Zaujímalo by ma, či bude užitočné, ak nie na otázku autora, budúcich čitateľov.
halfer

V iných jazykoch

Táto stránka je v iných jazykoch

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................