Maison  >  Article  >  développement back-end  >  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
WBOYavant
2024-02-09 11:33:09547parcourir

主 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)

}

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
    }
}

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