Maison > développement back-end > Golang > Impossible de recevoir la dernière valeur envoyée le long du canal dans la goroutine principale Golang

Impossible de recevoir la dernière valeur envoyée le long du canal dans la goroutine principale Golang

WBOY
Libérer: 2024-02-09 11:33:09
avant
555 Les gens l'ont consulté

主 goroutine Golang 中无法接收沿通道发送的最后一个值

Impossible de recevoir la dernière valeur envoyée le long du canal dans la goroutine principale Golang. En effet, lorsque le canal est fermé, la goroutine ne peut plus recevoir de nouvelles valeurs. Au lieu de cela, il bloque l'opération de réception jusqu'à ce que toutes les valeurs du canal aient été reçues. Il s'agit d'un choix de conception dans Golang pour éviter d'éventuelles situations de blocage lors des opérations de réception. Par conséquent, nous devons y prêter une attention particulière lors de l’écriture de programmes Golang afin d’éviter des problèmes et des erreurs potentiels.

Contenu de la question

Étant donné le scanner de port TCP dans Golang. 2 implémentations, la première est la mienne et la seconde vient du livre Golang. Supposons que le second soit réalisable à 100 %, comme de nombreux lecteurs l’ont déjà testé. Mais il semble que les deux aient le même problème : la dernière valeur envoyée dans le canal result ne peut pas être reçue dans la coroutine principale, elle reste bloquée en attendant indéfiniment la valeur du canal, bien que la valeur soit réellement envoyée. Quelques observations : Lorsque le nombre de ports est inférieur à 21, cela fonctionne comme prévu ; lorsque le montant dépasse 1000, le montant non reçu passe à environ 10. Je ne comprends pas pourquoi.

Mise en œuvre dans le livre

func worker(ports, results chan int) {
    for p := range ports {
        address := fmt.Sprintf("scanme.nmap.org:%d", p)
        conn, err := net.Dial("tcp", address)
        if err != nil {
            results <- 0
            fmt.Println("sent", p)
            continue
        }
        conn.Close()
        results <- p
        fmt.Println("sent", p)
    }
}

func main() {
    ports := make(chan int, 100)
    results := make(chan int)

    var openports []int

    for i := 0; i < cap(ports); i++ {
        go worker(ports, results)
    }

    go func() {
        for i := 1; i <= 50; i++ {
            ports <- i
        }
    }()

    for i := 0; i < 50; i++ {
        port := <-results // after 49 it gets stuck infinitely, never proceed further
        fmt.Println("received", port, i)
        if port != 0 {
            openports = append(openports, port)
        }
    }

    close(ports)
    close(results)

    sort.Ints(openports)

    fmt.Println(openports)

}
Copier après la connexion

Solution de contournement

Ce problème a été résolu en ajoutant un délai d'attente à net.Dialer

func worker(ports, results chan int) {
    dialer := net.Dialer{Timeout: time.Second}

    for p := range ports {
        address := fmt.Sprintf("scanme.nmap.org:%d", p)
        conn, err := dialer.Dial("tcp", address)
        if err != nil {
            results <- 0
            continue
        }

        conn.Close()
        results <- p
    }
}
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