帶有select 的goroute 不會在沒有fmt.Print() 的情況下終止
在Go Tour 練習#71 中,帶有select 語句的goroute除非在預設情況下加入fmt.Print() 語句,否則將連續執行。出現此行為的原因是存在預設語句時 select 的操作發生了變化。
如果沒有預設語句,select 會阻塞,直到在任何正在監視的頻道上收到訊息為止。透過新增預設值,只要沒有通道有訊息,select就會執行預設分支。
在原始程式碼中,default語句建立了一個無限迴圈:
for { select { case todo := <-toDoList: ... case <-doneCrawling: ... default: if os.Args[1] == "ok" { fmt.Print("") } if crawling == 0 { goto END } } }
沒有fmt。預設情況下,調度器無法調度其他goroutine,從而導致死鎖。新增 fmt.Print() 可以讓調度程式繼續其正常功能,從而使 goroutine 能夠完成。
修改程式碼以使用非阻塞 select 可以解決問題:
for { select { case todo := <-toDoList: ... case <-doneCrawling: ... } if crawling == 0 { break } }
或者,可以透過設定 GOMAXPROCS=2 來使原始程式碼正常運作,這表示排程器過載存在問題。
以上是為什麼 Go 的 select 語句需要 fmt.Print() 來終止特定的 Goroutine?的詳細內容。更多資訊請關注PHP中文網其他相關文章!