golang面試官:for select時,若是通道已經關閉會怎麼樣?若是select中只有一個case呢?

golang面試官:for select時,若是通道已經關閉會怎麼樣?若是select中只有一個case呢?

問題

for循環select時,若是通道已經關閉會怎麼樣?若是select中的case只有一個,又會怎麼樣?golang

怎麼答

  • for循環 select時,若是其中一個case通道已經關閉,則每次都會執行到這個case。
  • 若是select裏邊只有一個case,而這個case被關閉了,則會出現死循環。

解釋

1.for循環裏被關閉的通道

  • c通道是一個緩衝爲 0的通道,在 main開始時,啓動一個協程對 c通道寫入 10,而後就關閉掉這個通道。
  • main中經過 x, ok := <-c 接受 通道c裏的值,從輸出結果裏看出,確實從通道里讀出了以前塞入通道的 10,可是在通道關閉後,這個通道一直能讀出內容。

2.怎麼樣才能不讀關閉後通道

  • x, ok := <-c 返回的值裏第一個x是通道內的值, ok是指通道是否關閉,當通道被關閉後, ok則返回 false,所以能夠根據這個進行操做。讀一個已經關閉的通道爲何會出現false,能夠看我以前的 對已經關閉的的chan進行讀寫,會怎麼樣?爲何?
  • 當返回的 okfalse時,執行 c = nil 將通道置爲 nil,至關於讀一個未初始化的通道,則會一直阻塞。至於爲何讀一個未初始化的通道會出現阻塞,能夠看個人另外一篇 對未初始化的的chan進行讀寫,會怎麼樣?爲何?select中若是任意某個通道有值可讀時,它就會被執行,其餘被忽略。則 select會跳過這個阻塞 case,能夠解決不斷讀已關閉通道的問題。

3.若是select裏只有一個已經關閉的case,會怎麼樣?

  • 能夠看出只有一個 case的狀況下,則會 死循環
  • 那若是像上面一個 case那樣,把通道置爲 nil就能解決問題了嗎?

4.select裏只有一個已經關閉的case,置爲nil,會怎麼樣?

  • 第一次讀取 case能讀到通道里的 10
  • 第二次讀取 case能讀到通道已經關閉的信息。此時將通道置爲 nil
  • 第三次讀取 case時main協程會被阻塞,此時整個進程沒有其餘活動的協程了,進程 deadlock

總結

  • select中若是任意某個通道有值可讀時,它就會被執行,其餘被忽略。
  • 若是沒有 default字句, select將有可能阻塞,直到某個通道有值能夠運行,因此 select裏最好有一個 default,不然將有一直阻塞的風險。

文章推薦:

若是你想天天學習一個知識點?
相關文章
相關標籤/搜索