問題:
Go Tour 演習内#71、 go run 71_hang.go nogood を使用すると、 go run 中にプログラムが無期限に実行されます。 71_hang.go OK は期待どおりに動作します。唯一の違いは、select ステートメントのデフォルトのケースに fmt.Print("") が追加されていることです。
説明:
select ステートメントのデフォルトのステートメントが変更されます。ステートメントの動作。デフォルトを使用しない場合は、チャネルにメッセージが表示されるまでブロックを選択します。デフォルトでは、チャネルから読み取るものがなくなるたびに、select はデフォルトのステートメントを実行します。
元のコードでは、default ステートメントにより無限ループが作成されます。スケジューラは他のゴルーチンをスケジュールできないため、プログラムは無限に実行されます。
解決策 1:
デフォルトのステートメントを削除し、非ブロック選択を使用します:
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 } }
解決策2:
デフォルトのステートメントを保持しますが、ゴルーチンが必ず結果を返すようにします。これを実現する 1 つの方法は、GOMAXPROCS=2 を使用することです。これにより、スケジューラーが複数のコアを使用できるようになります。
追加の注意:
Goroutine は協調的にスケジュールされます。 Select は、ゴルーチンが譲歩すべきポイントです。ただし、指定された例で、fmt.Print() ステートメントがないと select が生成されない理由は完全には理解されていないため、さらなる調査が必要です。
以上が「default」ケースを使用しないと Go の「select」ステートメントがハングするのはなぜですか?それを修正するにはどうすればよいですか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。