Goroutine with Select Doesn't Stop Unless a Print Statement is Added
In the Go Tour exercise #71, using select without a default statement can result in an infinite loop that prevents the goroutine from exiting. This issue is encountered when running 71_hang.go with the nogood argument, but not with the ok argument.
The difference between the two scenarios is the presence of an additional fmt.Print("") statement in the default case of the select statement. By default, select blocks until one of the channels has a message to receive. However, with the default case, select will execute the default statement even if none of the channels have messages available.
In the original code, without the fmt.Print("") statement, the select statement entered an infinite loop because there were no channels with messages available, and the default case was not doing anything to allow the goroutine to schedule. Adding the fmt.Print("") statement allowed the scheduler to schedule other goroutines and break the infinite loop.
Alternatively, the code can be modified to use select in a non-blocking way, allowing the other goroutines to run properly. This can be achieved by removing the default statement and using a separate if statement to check if the crawling counter has reached zero, as shown in the modified code below:
for { select { case todo := <-toDoList: if todo.depth > 0 && !visited[todo.url] { crawling++ visited[todo.url] = true go crawl(todo, fetcher, toDoList, doneCrawling) } case <-doneCrawling: crawling-- } if crawling == 0 { break } }
The above is the detailed content of Why Does a Go Select Statement with a Goroutine Hang Unless a Print Statement is Added?. For more information, please follow other related articles on the PHP Chinese website!