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.
É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) }
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!