La lectura de una goroutine canal sin bloqueo

0

Pregunta

Tengo dos goroutines: el principal worker y un helper que no deja de girar por un poco de ayuda. helper pueden producirse errores, por lo que utilizar un canal para comunicar errores a lo largo de la helper a la worker.

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

Aquí es cómo helper() se llama:

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

Preguntas:

  • Es la declaración de err := <- c el bloqueo de worker? No lo creo, ya que el canal está en el búfer.

  • Si es el bloqueo, ¿cómo puedo hacer que el bloqueo no? Mi requisito es tener worker y su llamada a continuar con el resto de la obra, sin esperar por el valor que aparezca en el canal.

Gracias.

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

Mejor respuesta

2

Usted puede comprobar fácilmente

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: Es la declaración err := <- c bloqueo del trabajador? No lo creo, ya que el canal está en el búfer.

Una: err := <- c el bloque de trabajador.

P: Si es el bloqueo, ¿cómo puedo hacer que el bloqueo no? Mi requisito es tener el trabajador y su llamador continuar con el resto de la obra, sin esperar a que el valor que aparezca en el canal.

R: Si usted no desea bloquear, acaba de quitar err := <-c. Si usted necesita errar al final, sólo se mueven err := <-c para el final.

Usted no puede leer los canales sin bloqueo, si usted va a través de sin bloqueo, puede no puede más exec este código, a menos que el código está en un bucle.

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

Y ¿alguna vez has visto errgroup o waitgroup?

El uso de la informática atómica, cancelar el contexto y la sincronización.Una vez que implementar esto.

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

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

O sólo se puede utilizar, vaya usted func y luego esperar a que el error en cualquier lugar que desee.

2021-12-01 21:31:34
1

En su código, el resto de la obra es independiente de si la ayuda se ha encontrado un error. Usted puede simplemente recibir de la canal después de que el resto de la obra se ha completado.

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

Bueno, ¿no trabajador() se bloquea hasta que aparece un valor en c?
Someone

También, me acaba de editar worker(). Devuelve el error/nil a su llamador. Así, esta operación se bloquea?
Someone

Sí esa operación en particular se bloqueará hasta que helper envía un error o nil para el canal. Pero el trabajador está bloqueado, sólo después de que ha completado todos sus trabajos.
Chandra Sekar

Pero que bloquea la llamada de worker. Es allí una manera de hacer que el bloqueo no?
Someone

Si el trabajador, y en consecuencia, su persona, no espere ayuda para completar, ¿cómo puede devolver el error de ayudante?
Chandra Sekar
0

Creo que es necesario este código..

ejecutar este código

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

Puede usted explicar, por medio de una edición para esta respuesta, ¿por qué esto podría ayudar? Me pregunto si esto va a ser útil, si no a la pregunta de autor, para los lectores futuros.
halfer

En otros idiomas

Esta página está en otros idiomas

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