A leitura de uma goroutine canal sem bloqueio

0

Pergunta

Eu tenho dois goroutines: o principal worker e um helper que gira para alguma ajuda. helper pode encontrar erros, então eu uso um canal para se comunicar erros ao longo do helper para o worker.

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

É aqui como helper() é chamado de:

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

Perguntas:

  • É a declaração de err := <- c bloqueio worker? Eu não penso assim, já que o canal é armazenada em buffer.

  • Se ele está bloqueando, como posso fazer isso sem bloqueio? A minha exigência é ter worker e seu chamador continuar com o resto da obra, sem espera, para que o valor exibido no canal.

Obrigado.

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

Melhor resposta

2

Você pode facilmente verificar

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: É a instrução de mensagem := <- c o bloqueio do trabalhador? Eu não penso assim, já que o canal é armazenada em buffer.

A: err := <- c irá bloquear o trabalhador.

Q: Se ele está bloqueando, como posso fazer isso sem bloqueio? A minha exigência é ter o trabalhador e seu chamador continuar com o resto da obra, sem esperar que o valor para aparecer no canal.

A: Se você não quiser bloquear, basta remover err := <-c. Se você precisa de mensagem, no final, basta mover err := <-c para o final.

Você não pode ler canal sem o bloqueio, se você ir até o fim sem bloqueio, pode não podem mais exec este código, a menos que o seu código está em um loop.

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

E você já viu errgroup ou waitgroup?

Ele usa atômica, cancelar contexto e de sincronização.Uma vez para implementar isso.

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

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

Ou você pode simplesmente usá-lo, vá você func e, em seguida, aguarde erro em qualquer lugar que você quiser.

2021-12-01 21:31:34
1

No seu código, o resto do trabalho é independente de se a auxiliar encontrou um erro. Você pode simplesmente receber o canal depois que o resto da obra está concluída.

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

Bem, não trabalho() ser bloqueado até que o valor aparece no c?
Someone

Também, eu só editado worker(). Ele retorna o erro/nulo para o seu chamador. Por isso, esta operação ser bloqueado?
Someone

Sim que determinada operação, será bloqueado até auxiliar envia uma error ou nil para o canal. Mas trabalhador é bloqueado somente depois de ter concluído os seus trabalhos.
Chandra Sekar

Mas o que bloqueia o chamador de worker. Existe uma maneira para torná-lo não-bloqueio?
Someone

Se o trabalhador, e, consequentemente, o seu interlocutor, não espere para auxiliar a concluir, como ele pode retornar o erro do auxiliar?
Chandra Sekar
0

Eu acho que você precisa deste código.

executar 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

Você pode explicar, por meio de uma edição para esta resposta, por isso ajudaria? Eu me pergunto se isso vai ser útil, se não para a pergunta do autor, para futuros leitores.
halfer

Em outros idiomas

Esta página está em outros idiomas

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