La lettura da un goroutine canale senza blocco

0

Domanda

Ho due goroutines: il principale worker e un helper che si gira fuori per aiuto. helper possono verificarsi degli errori, in modo da utilizzare un canale per comunicare con errori da helper per il worker.

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

Ecco come helper() si chiama:

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

Domande:

  • È la dichiarazione err := <- c il blocco worker? Io non la penso così, dal momento che il canale è memorizzato nel buffer.

  • Se si blocca, come posso fare per non bloccare? La mia esigenza è quella di avere worker e il suo chiamante continuare con il resto dell'opera, senza l'attesa per il valore visualizzato sul canale.

Grazie.

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

Migliore risposta

2

Si può facilmente verificare

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: È la dichiarazione err := <- c il blocco operaio? Io non la penso così, dal momento che il canale è memorizzato nel buffer.

A: err := <- c blocca lavoratore.

Q: Se si blocca, come posso fare per non bloccare? La mia esigenza è quella di avere lavoratore e il suo chiamante continuare con il resto dell'opera, senza attendere che il valore visualizzato sul canale.

A: Se non si desidera che il blocco, è sufficiente rimuovere err := <-c. Se avete bisogno di err alla fine, basta spostare err := <-c alla fine.

Non si può leggere canale senza blocco, se si passa attraverso senza blocco, può non può più exec questo codice, a meno che il tuo codice è in un ciclo.

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

E avete mai visto errgroup o waitgroup?

Non utilizzare atomica, annulla il contesto e la sincronizzazione.Una volta per implementare questo.

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

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

Oppure si può semplicemente utilizzare, si func e quindi attendere per errore in qualsiasi luogo desideri.

2021-12-01 21:31:34
1

Nel codice, il resto del lavoro è indipendente se il figurante si è verificato un errore. Si può semplicemente ricevere dal canale dopo che il resto del lavoro è stato completato.

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

Beh, non lavoratore() bloccato fino a quando non viene visualizzato un valore su c?
Someone

Inoltre, ho appena modificato worker(). Restituisce l'errore/nil al chiamante. Così, questa operazione di essere bloccato?
Someone

Sì quella particolare operazione di blocco finché non helper invia un error o nil per il canale. Ma il lavoratore è bloccato solo dopo aver completato tutto il suo lavoro.
Chandra Sekar

Ma che blocca il chiamante di worker. C'è un modo per rendere non-blocking?
Someone

Se il lavoratore, e, di conseguenza, il suo chiamante, non aspettare helper per completare, come si può restituire l'errore da helper?
Chandra Sekar
0

Penso che avete bisogno di questo codice..

eseguire questo codice

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

Puoi spiegare, per via di una modifica di questa risposta, perché questo sarebbe di aiuto? Mi chiedo se possa essere utile, se non per l'autore questione, per i futuri lettori.
halfer

In altre lingue

Questa pagina è in altre lingue

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