不要等離職了,才知道for select時,若是通道已經關閉會怎麼樣?

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,不然將有一直阻塞的風險。

    文章推薦:

    若是你想天天學習一個知識點?

    相關文章
    相關標籤/搜索