Maison  >  Article  >  développement back-end  >  Il y a un problème avec le canal Go, envoi sur un canal fermé

Il y a un problème avec le canal Go, envoi sur un canal fermé

WBOY
WBOYavant
2024-02-11 18:21:081243parcourir

go 通道出现问题,在封闭通道上发送

L'éditeur php Youzi peut rencontrer certains problèmes lors du processus de développement en utilisant le langage Go. L'un d'eux est le problème lors de l'envoi de données sur un canal fermé. Ce problème peut provoquer un blocage des chaînes et une stagnation du programme, affectant le fonctionnement de l'ensemble de l'application. Avant de résoudre ce problème, nous devons d’abord comprendre ce qu’est un canal fermé et pourquoi l’envoi de données sur un canal fermé est problématique. Ensuite, nous approfondirons ce problème et proposerons des solutions pour réparer et optimiser nos applications Go.

Contenu de la question

J'obtiens une erreur fatale : "Envoi sur un canal fermé" et parfois j'exécute ce code, j'ai essayé plusieurs solutions mais aucune n'a fonctionné, voici la représentation du code, facile à comprendre et à utiliser test d'usage :

CB14CE50B218D8EAB916B15CD95527D5

Ce que je veux, c'est démarrer la fonction de requête n fois et obtenir la première requête terminée, puis fermer le canal et ne plus envoyer de requêtes au canal, si aucune des requêtes ne se termine avec succès, attendez que toutes les goroutines se terminent.

Je suppose que cela se produit parce que deux goroutines ou plus vérifient si le canal est fermé en même temps, et toutes deux essaient d'écrire dans le canal, ce qui entraîne une erreur fatale.

Erreur :

goroutine 19 [running]:
main.request(0xc00000a028, 0xc00000a030, 0x0?)
        C:/test/main.go:49 +0x135
created by main.main
        C:/test/main.go:17 +0xd3
panic: send on closed channel

Quelqu'un peut-il expliquer pourquoi cela se produit ?

Merci d'avance

Solution de contournement

Le problème vient de la goroutine de réception (main) 过早关闭 outputCh. Une autre goroutine peut toujours essayer d'envoyer dessus.

Voici une autre façon :

package main

import (
    "fmt"
    "math/rand"
    "sync"
    "time"
)

func main() {
    var wg sync.WaitGroup
    output := make(chan string)
    stop := make(chan bool)
    done := make(chan bool)

    for i := 0; i < 20; i++ {
        wg.Add(1)
        go request(output, stop, &wg)
    }

    go func() {
        wg.Wait()
        done <- true
    }()

    firstOutput := <-output
    fmt.Println("output:", firstOutput)

    fmt.Println("closing the stop channel")
    close(stop)

    <-done
    fmt.Println("end of main")
}

func request(output chan string, stop chan bool, wg *sync.WaitGroup) {
    defer wg.Done()

    fmt.Println("request started")
    time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond)

    select {
    case output <- "test":
        fmt.Println("output sent")
    case <-stop:
        fmt.Println("stop channel is closed")
    }
}

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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer