golang 面試官:for select 時,如果通道已經關閉會怎麼樣?如果只有一個 case 呢?
今天咱們聊點技術性的東西,具體說一下 Go 語言中的 for select
語句,特別是在面試中經常被問到的兩個問題。
題目 1:for select
語句中,如果通道已經關閉了,會怎麼樣?
這道題乍一聽簡單,但其實是面試官最喜歡用來考察你是否真正理解 Go 中通道機制的題目之一。假設你在寫一個需要從通道讀取數據的程序,然後突然有人關了通道,你會怎麼處理?程序會怎麼樣?如果你把這個問題想得很簡單,你可能會以爲它只是個 “錯誤處理” 的問題,但是 Go 的通道在關閉時的行爲是有特殊規則的,搞清楚這些規則對寫出高質量代碼非常重要。
閉合通道的行爲
在 Go 中,通道是一個用於在 goroutine 之間傳遞數據的管道。如果你對 select
語句不太熟悉,我可以簡短地回顧一下它的工作方式。select
就是 Go 語言中多路複用的選擇語句,它監聽多個通道的消息,並在某個通道有數據時執行對應的代碼塊。代碼大概像這樣:
select {
case msg := <-ch1:
fmt.Println("Received:", msg)
case msg := <-ch2:
fmt.Println("Received:", msg)
case <-time.After(1 * time.Second):
fmt.Println("Timeout")
}
在這個例子裏,select
等待從 ch1
或 ch2
獲取數據,或者等到超時。如果這些通道都沒有數據,它就會阻塞等待。
那麼,如果某個通道已經關閉了,會發生什麼呢?這時候通道的行爲就很特別了。我們來逐步分析:
-
從已關閉的通道讀取數據: 如果你從已經關閉的通道讀取數據,Go 會立刻返回該通道的零值。舉個例子,如果你有一個
int
類型的通道,當它關閉時,從中讀取數據將始終返回0
(零值)。你可能覺得這有點兒反直覺,但這就是 Go 的設計。 -
select
中的關閉通道: 如果你在select
語句中選擇了一個已經關閉的通道,它將立刻進入對應的case
分支。如果有多個通道同時滿足條件,它會選擇已經關閉的通道並處理它。 -
是否會阻塞? 如果通道關閉時,且沒有更多的數據要發送,
select
將不再阻塞並立即跳到對應的case
。但是,如果你在select
中一直在等待某個通道的消息,它會在通道關閉後正常執行,但不會再等待該通道的數據了。
代碼示例
package main
import (
"fmt"
)
func main() {
ch := make(chan int, 1)
close(ch) // 關閉通道
select {
case msg := <-ch:
fmt.Println("Received:", msg)
default:
fmt.Println("No data received")
}
}
在這段代碼裏,通道 ch
在被關閉後會直接進入 select
語句的 case msg := <-ch:
分支,輸出的是 0
,因爲 ch
被關閉並且已經沒有數據了。如果你把 ch
關閉後再發送數據,數據不會被接收。實際上,關閉通道時需要小心,尤其是在高併發環境下,容易導致數據丟失。
題目 2:如果 select
語句中只有一個 case
,會怎麼樣?
這個問題相對簡單,但是也能檢驗你對 select
的理解。
假設你在使用 select
時,只有一個 case
,會發生什麼呢?根據 Go 語言的文檔,select
是一個阻塞操作,如果只有一個 case
並且通道有數據可讀,select
會立即執行該 case
。如果沒有數據可讀,它就會一直阻塞等待數據。
那麼,這個問題的本質是,select
會一直阻塞直到某個通道能夠處理數據。如果只有一個 case
,那麼只有該通道準備好時,select
纔會被觸發。
示例代碼
package main
import (
"fmt"
)
func main() {
ch := make(chan int)
// 這裏啓動一個 goroutine 來給通道發送數據
go func() {
ch <- 42
}()
select {
case msg := <-ch:
fmt.Println("Received:", msg)
}
}
在這段代碼中,我們只有一個 case
,並且通過一個 goroutine 向通道 ch
發送數據。當數據準備好時,select
會立刻執行。如果沒有數據,它就會一直阻塞在這裏,不會繼續執行下面的代碼。
總結
這兩個問題看似簡單,但它們分別考察了你對 Go 通道工作機制的掌握程度,尤其是通道關閉時的行爲。正確理解 Go 的通道關閉與 select
的阻塞特性,是避免寫出錯誤代碼的關鍵。如果你正在爲面試做準備,記得在面試時解釋清楚這些行爲。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/Fjf9x95tJXlFxsHt_415wg