Lecture à partir d'une goroutine canal sans blocage

0

La question

J'ai deux goroutines: le principal worker et un helper qu'il lance pour de l'aide. helper pouvez rencontrer des erreurs, j'ai donc utiliser un canal pour communiquer les erreurs au cours de la helper à l' worker.

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

Voici comment helper() est appelé:

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

Questions:

  • La déclaration err := <- c blocage worker? Je ne le pense pas, car le canal est mis en mémoire tampon.

  • Si c'est le blocage, comment dois-je le faire sans blocage? Mon exigence est d'avoir worker et son appelant continuer avec le reste de l'œuvre, sans attente pour la valeur à apparaître sur le canal.

Merci.

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

La meilleure réponse

2

Vous pouvez facilement vérifier

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: Est-ce l'état, err := <- c blocage de travailleur? Je ne le pense pas, car le canal est mis en mémoire tampon.

Un: err := <- c va bloquer travailleur.

Q: Si c'est le blocage, comment dois-je le faire sans blocage? Ma condition est de disposer d'un travailleur et son appelant continuer avec le reste de l'œuvre, sans attendre que la valeur apparaisse sur le canal.

A: Si vous ne voulez pas de blocage, il suffit de retirer err := <-c. Si vous avez besoin d'err à la fin, il suffit de déplacer err := <-c jusqu'à la fin.

Vous ne pouvez pas lire le canal sans blocage, si vous passez par sans blocage, peut pas plus exec ce code, à moins que votre code est dans une boucle.

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

Et avez-vous déjà vu errgroup ou waitgroup?

C'utilisation atomique, annuler contexte et de synchronisation.Une fois à le mettre en œuvre.

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

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

Ou vous pouvez simplement l'utiliser, allez vous func, puis attendez que l'erreur n'importe où vous voulez.

2021-12-01 21:31:34
1

Dans votre code, le reste du travail est indépendant du fait que l'aide a rencontré une erreur. Vous pouvez simplement recevoir de la manche après le reste de l'œuvre est achevée.

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

Eh bien, n'est pas un travailleur() sera bloqué jusqu'à ce qu'une valeur apparaît sur c?
Someone

Aussi, j'ai juste édité worker(). Elle renvoie l'erreur/nul à son appelant. C'est le cas, cette opération doit être bloqué?
Someone

Oui, cette opération se bloque jusqu'à ce helper envoie un error ou nil pour le canal. Mais travailleur est bloqué seulement après qu'il a rempli tous ses travaux.
Chandra Sekar

Mais qui bloque l'appelant de worker. Est-il un moyen de le rendre non-bloquant?
Someone

Si le travailleur, et, par conséquent, son appelant, ne pas attendre de l'aide pour terminer, comment peut-il retourner l'erreur de l'aide?
Chandra Sekar
0

Je pense que vous avez besoin de ce code..

exécutez ce code

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

Pouvez-vous expliquer, par le biais d'une modification de cette réponse, pourquoi ce serait aider? Je me demande si cela sera utile, si ce n'est à l'auteur de la question, pour les futurs lecteurs.
halfer

Dans d'autres langues

Cette page est dans d'autres langues

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