Odczyt z kanału goroutine bez blokady

0

Pytanie

Mam dwie горотины: strona główna worker i helper co obraca się do jakiejś pomocy. helper mogą pojawić się błędy, więc używam kanał do transmisji błędów helper do worker.

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

Oto jak helper() nazywa się:

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

Pytania:

  • Czy stwierdzenie err := <- c blokowanie worker? Nie sądzę, tak jako kanał буферизован.

  • Jeśli zostanie on zablokowany, jak mi się zrobić go nieblokujące? Moje wymóg polega na tym, aby mieć worker i jego abonent nadal pozostałą część pracy, nie czekając, aż wartość pojawi się na kanale.

Dziękuję.

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

Najlepsza odpowiedź

2

Można łatwo sprawdzić

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

Pytanie: czy Jest to twierdzenie błędne := Ja tak nie myślę, tak jak kanał буферизован.

Odpowiedź: err := <- c zablokuje pracownika.

Pytanie: Jeśli on zablokowany, jak mi się zrobić go nieblokujące? Moje wymogiem jest to, aby pracownik i jego rozmówca nadal wykonywać resztę pracy, nie czekając na pojawienie się wartości na kanale.

Odpowiedź: Jeśli nie chcesz blokady, po prostu usuń err := <-c. Jeśli potrzebujesz pomylić w końcu, po prostu ruszaj się err := <-c aż do samego końca.

Nie można odczytać kanał bez blokady, jeśli przechodzą bez blokady, nie można już wykonać ten kod, jeśli tylko twój kod nie znajduje się w cyklu.

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

I czy kiedykolwiek widziałeś grupę błędów lub grupę gotowości?

Używa bloku jednorazowego, zastępuje kontekst i synchronizację.Jeden raz, aby tego dokonać.

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

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

Lub możesz po prostu użyć go wykonać swoją funkcję, a następnie czekać na błędy w dowolnym miejscu, gdzie tylko chcesz.

2021-12-01 21:31:34
1

W kodzie pozostała część pracy nie zależy od tego, odkrył czy asystent błąd. Możesz po prostu wziąć z kanału po zakończeniu reszty pracy.

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 chyba roboczy() nie zostanie zablokowany do momentu, aż wartość nie pojawi się na c?
Someone

Poza tym, dopiero co był edytowany przez worker(). Wraca do wywołującego błąd/zero. Tak więc, czy ta operacja jest zablokowana?
Someone

Tak, ta konkretna operacja zostanie zablokowana do momentu, gdy asystent nie wyśle error lub nil na kanał. Ale pracownik jest zablokowana po tym, jak wykonał całą pracę.
Chandra Sekar

Ale to blokuje możliwość worker. Czy istnieje sposób, aby zrobić to nieblokujące?
Someone

Jeżeli pracownik i, w konsekwencji, jego osoba dzwoniąca nie czeka na zakończenie pracy asystenta, jak on może zwrócić błąd od asystenta?
Chandra Sekar
0

Myślę, że trzeba ten kod..

uruchom ten kod

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

Czy możesz wyjaśnić, edytując tę odpowiedź, dlaczego to pomoże? Ciekawe, czy będzie to przydatne, jeśli nie autorowi pytania, to w przyszłym czytelnikom.
halfer

W innych językach

Ta strona jest w innych językach

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