Čtení z goroutine kanál bez blokování

0

Otázka

Mám dvě goroutines: hlavní worker a helper to, že to lupne pro pomoc. helper můžete narazit na chyby, takže jsem použít kanál pro komunikaci chyby z helper k worker.

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

Zde je, jak helper() se nazývá:

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

Otázky:

  • Je prohlášení err := <- c blokování worker? Nemyslím si, že tak, protože kanál je vyrovnávací paměti.

  • Pokud je blokování, jak mám udělat, aby to non-blocking? Můj požadavek je, aby worker a jeho volajícího pokračovat s zbytek práce, bez čekání na hodnoty, které se objeví na kanálu.

Díky.

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

Nejlepší odpověď

2

Můžete snadno ověřit

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

Q: Je prohlášení err := <- c blokování pracovníka? Nemyslím si, že tak, protože kanál je vyrovnávací paměti.

A: err := <- c bude blokovat pracovník.

Q: Pokud je blokování, jak mám udělat, aby to non-blocking? Můj požadavek je, aby pracovník a jeho volajícího pokračovat s zbytek práce, aniž by čekal na hodnotu, aby se objeví na kanálu.

A: Pokud nechcete blokovat, stačí odstranit err := <-c. Pokud potřebujete err na konci, jen přesunout err := <-c až do konce.

Nemůžete přečíst kanál bez blokování, pokud jste projít bez blokování, může ne více exec tento kód, pokud je kód ve smyčce.

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

A už jste někdy viděli errgroup nebo waitgroup?

To použití atomové, zrušit kontextu a synchronizace.Jednou realizovat.

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

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

Nebo můžete jen použít to, jít si func a pak čekat na chyby v jakémkoli místě, které chcete.

2021-12-01 21:31:34
1

V kódu, zbytek práce je nezávislý na tom, zda helper došlo k chybě. Můžete jednoduše získat z kanálu po zbytek práce je dokončena.

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

No, nechtěl pracovníka (v) být blokován dokud hodnota se objeví na c?
Someone

Také, jen jsem upravil worker(). Vrací se chyba/nil do jeho volajícího. Takže by tato operace byla blokována?
Someone

Ano, které konkrétní operace bude blokovat, dokud pomocník odešle error nebo nil do kanálu. Ale pracovník je blokován pouze poté, co dokončil všechny jeho práce.
Chandra Sekar

Ale, že blokuje volající worker. Existuje způsob, jak dělat to non-blocking?
Someone

Pokud pracovník, a proto jeho volajícího, ne čekat, pomocník dokončit, jak se může vrátit chybovou od pomocníka?
Chandra Sekar
0

Myslím, že budete potřebovat tento kód..

spustit 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 vysvětlit, o způsob, jak upravit tato odpověď, proč by to pomohlo? Zajímalo by mě, jestli to bude užitečné, pokud ne, na otázku autora, aby budoucí čtenáři.
halfer

V jiných jazycích

Tato stránka je v jiných jazycích

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