Maison > développement back-end > Golang > Un moyen sûr de mettre fin à un goroutine en boucle infinie ?

Un moyen sûr de mettre fin à un goroutine en boucle infinie ?

WBOY
Libérer: 2024-02-06 09:09:04
avant
1014 Les gens l'ont consulté

终止无限循环 goroutine 的安全方法?

Contenu de la question

J'ai une goroutine qui fait office d'auditeur. Le flux d'entrée arrive dans un tampon channel,我希望我的 goroutine 处理传入该通道的数据。然而,有时 channel 可能会暂时没有数据输入。如果 channel qui n'a rien à offrir pendant une seconde et je veux que ma goroutine fasse quelque chose de différent. La fonction ressemble à ceci :

func main () {
    var wg sync.WaitGroup
    arr := make([]*myObject, 0)
    wg.Add(1)
    go listener(c, arr, &wg)
    for {
        // sending stuff to c
    }
}

func listener(c chan *myObject, arr []*myObject, wg *sync.WaitGroup) {
    for {
        select {
        case value := <- c:
            arr = append(arr, value)
        case <- time.After(1 * time.Second):
            fmt.Println(arr)
        }
}
Copier après la connexion

Le problème est que je veux voir imprimé tout ce qui passe par ce canal. Si la position de main 突然结束,可能 arr 中还剩下一些东西还没有打印出来,我就看不到了。所以我需要确保这个goroutine在程序结束之前处理完通道中的所有数据。我认为,这意味着我需要使用 WaitGroup 并使用 Wait() 来确保程序在我的 goroutine 完成需要执行的操作之前不会关闭。 但我不知道在我的 WaitGroup 上调用 Done().

En gros, j'ai besoin d'un moyen sûr de "mettre en pause" la goroutine avant la fin du programme et d'imprimer ce qui reste. Comment puis-je faire ceci?

Pour aggraver les choses, pour des choses comme les tests unitaires, j'envoie moi-même des données au canal et après avoir envoyé une certaine quantité, je souhaite voir le tableau. Cependant, si je vérifie simplement le tableau juste après le code qui envoie les données au canal, la goroutine n'a peut-être pas encore eu la possibilité de traiter toutes les données. Dans ce cas, je veux attendre que la goroutine traite toutes les données que j'envoie, puis je veux la mettre en pause et lui demander de me montrer le tableau. Mais comment puis-je savoir quand la goroutine a terminé le traitement ? Je pourrais sleep attendre un moment, lui donner une chance de terminer, puis m'arrêter et le regarder, mais cela semble plutôt compliqué. Je pense qu'il existe une bonne pratique pour résoudre ce problème, mais je ne l'ai pas encore compris.

Voici quelques idées que j'avais, aucune d'entre elles n'a fonctionné.

  1. à l'infini for 循环之外调用 Done(). Cela ne fonctionne pas car à ma connaissance, le code n'est pas accessible.

  2. En délai d'attentecase中调用Done(). Cela ne fonctionne pas car après le délai d'attente, il peut y avoir plus de données en route et je veux que ma goroutine continue d'écouter.


Bonne réponse


Modifiez l'auditeur pour qu'il revienne lorsque la chaîne est fermée. Appelez wg.Done() au retour :

func listener(c chan *myObject, arr []*myObject, wg *sync.WaitGroup) {
    defer wg.Done()
    for {
        select {
        case value, ok := <- c:
            if !ok { return }
            arr = append(arr, value)
        case <- time.After(1 * time.Second):
            fmt.Println(arr)
        }
}
Copier après la connexion

Modifiez main pour fermer la chaîne une fois l'envoi terminé. Attendez que la goroutine soit terminée avant de revenir du principal.

var wg sync.WaitGroup
arr := make([]*myObject, 0)
wg.Add(1)
go listener(c, arr, &wg)
for {
    // sending stuff to c
}
close(c)
wg.Wait()
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal