Home >Backend Development >Golang >Unable to receive last value sent along channel in main goroutine Golang
The main goroutine in Golang cannot receive the last value sent along the channel. This is because when the channel is closed, the goroutine cannot receive new values again. Instead, it blocks on the receive operation until all values in the channel have been received. This is a design choice in Golang to avoid possible deadlock situations during receive operations. Therefore, we need to pay special attention to this when writing Golang programs to avoid potential problems and errors.
Given TCP port scanner in golang. 2 implementations, the first is mine and the second is from the golang book. Assume the second one is 100% feasible, as many readers have tested before. But it seems that both have the same problem: the last value sent in the result channel cannot be received in the main coroutine, it gets stuck waiting infinitely for the value from the channel, despite the The value is actually sent. Some observations: When the number of ports is less than 21, it works as expected; when the amount exceeds 1000, the amount not received increases to around 10. I do not understand why.
Implementation in the book
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) }
This issue has been solved by adding a timeout to 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 } }
The above is the detailed content of Unable to receive last value sent along channel in main goroutine Golang. For more information, please follow other related articles on the PHP Chinese website!