Citirea dintr-o goroutine canal fără blocarea

0

Problema

Am două goroutines: principalele worker și o helper care se invarte off pentru ajutor. helper pot apărea erori, asa ca am folosi un canal pentru a comunica erori de helper la worker.

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

Aici este cum helper() se numește:

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

Întrebări:

  • Este declarația err := <- c blocarea worker? Nu cred, deoarece canalul este tamponat.

  • Dacă se blochează, cum pot face non-blocking? Cerința mea este de a avea worker și apelant sa continue cu restul de lucru, fără a aștepta pentru valoarea sa apar pe canal.

Multumesc.

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

Cel mai bun răspuns

2

Puteți verifica cu ușurință

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: Este declarația err := <- c blocarea lucrător? Nu cred, deoarece canalul este tamponat.

O: err := <- c va bloca lucrător.

Q: Dacă se blochează, cum pot face non-blocking? Cerința mea este de a fi lucrător și apelant sa continue cu restul de lucru, fără a aștepta pentru valoarea sa apar pe canal.

O: Dacă nu doriți blocarea, doar elimina err := <-c. Dacă aveți nevoie err în cele din urmă, doar muta err := <-c la final.

Nu puteți citi canal fără blocarea, dacă te duci prin, fără a bloca, poate poate nu mai exec acest cod, cu excepția cazului în care codul este într-o buclă.

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

Și ați văzut vreodată errgroup sau waitgroup?

Se folosesc atomic, anula context și de sincronizare.O dată pentru a pune în aplicare acest lucru.

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

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

Sau puteți pur și simplu utiliza, du-te tu func și apoi așteptați pentru eroare în orice loc doriți.

2021-12-01 21:31:34
1

În cod, restul de lucru este independent de faptul helper întâlnit o eroare. Pur și simplu, puteți primi de la canal în urma restul de lucru este finalizată.

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

Ei bine, nu-lucrător() fi blocat până la o valoare apare pe c?
Someone

De asemenea, am editat worker(). Returnează eroare/zero pentru apelant. Deci, această operațiune ar fi blocat?
Someone

Da, asta anumită operațiune va bloca până helper trimite un error sau nil la canal. Dar lucrătorul este blocat numai după ce acesta a finalizat toate lucrările sale.
Chandra Sekar

Dar care blochează apelantul a worker. Există o modalitate de a face non-blocking?
Someone

În cazul în care lucrătorul și, în consecință, apelant, nu așteptați pentru ajutor pentru a finaliza, cum poate returna eroare de helper?
Chandra Sekar
0

Cred că ai nevoie de acest cod..

rula acest cod

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

Puteți explica, printr-o modificare la acest răspuns, de ce acest lucru ar ajuta? Mă întreb dacă asta va fi util, dacă nu, la întrebarea autor, pentru viitorii cititori.
halfer

În alte limbi

Această pagină este în alte limbi

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