Go中select多路復用的實現示例
select 是 Go 并發(fā)編程中非常強大的語法結構,它允許程序同時等待多個通道操作的完成,從而實現多路復用機制,是協程調度、超時控制、通道競爭等場景的核心工具。
一、什么是select
select 類似于 switch 語句,但它用于監(jiān)聽多個通道的發(fā)送/接收操作。一旦其中任意一個通道準備就緒,select 就會執(zhí)行相應的語句塊。
基本語法:
select {
case val := <-ch1:
// ch1 可讀時執(zhí)行
case ch2 <- data:
// ch2 可寫時執(zhí)行
default:
// 所有通道都不準備好時執(zhí)行(可選)
}
二、select 使用示例
示例1:監(jiān)聽多個通道輸入
func main() {
ch1 := make(chan string)
ch2 := make(chan string)
go func() {
time.Sleep(1 * time.Second)
ch1 <- "消息來自 ch1"
}()
go func() {
time.Sleep(2 * time.Second)
ch2 <- "消息來自 ch2"
}()
select {
case msg1 := <-ch1:
fmt.Println(msg1)
case msg2 := <-ch2:
fmt.Println(msg2)
}
}
輸出(大概率):
消息來自 ch1
誰先準備好,誰被執(zhí)行。
三、select的特性
- 隨機選擇:如果多個
case同時滿足,Go 會隨機選擇一個執(zhí)行,避免饑餓。 - 阻塞行為:當沒有任何
case可以運行時,select會阻塞,除非有default。 - 可配合 for 使用:實現多路輪詢、協程調度等高級用法。
四、使用select實現超時機制
select 搭配 time.After() 可實現通道的超時控制:
select {
case msg := <-ch:
fmt.Println("收到消息:", msg)
case <-time.After(2 * time.Second):
fmt.Println("超時未收到")
}
實用場景:
- 網絡請求超時
- 等待任務執(zhí)行完成
- 控制并發(fā)阻塞時間
五、非阻塞通信:使用default
select {
case msg := <-ch:
fmt.Println("收到:", msg)
default:
fmt.Println("沒有收到任何數據")
}
不等待,立即返回默認分支。
六、監(jiān)聽通道關閉
配合 range 和 select,可以優(yōu)雅處理通道關閉:
for {
select {
case msg, ok := <-ch:
if !ok {
fmt.Println("通道已關閉")
return
}
fmt.Println("收到:", msg)
}
}
七、實踐:合并多個輸入通道
func merge(ch1, ch2 <-chan string) <-chan string {
out := make(chan string)
go func() {
for {
select {
case msg := <-ch1:
out <- msg
case msg := <-ch2:
out <- msg
}
}
}()
return out
}
? 實現“扇入”(fan-in)模式,將多個輸入流合并成一個輸出。
八、小結
| 功能 | 是否支持 |
|---|---|
| 同時監(jiān)聽多個通道 | ? |
| 隨機選擇就緒的通道執(zhí)行 | ? |
| 支持默認分支防止阻塞 | ? |
| 可實現超時控制與輪詢 | ? |
| 實現非阻塞收發(fā)或關閉判斷 | ? |
實戰(zhàn)建議
- 為所有關鍵的通道通信加上
select和超時控制,避免協程泄漏。 - 避免使用
select輪詢空通道導致死循環(huán)。 - 多通道合并、拆分時,配合
select和sync.WaitGroup效果更佳。
到此這篇關于Go中select多路復用的實現示例的文章就介紹到這了,更多相關Go select多路復用內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
go?mode?tidy出現報錯go:?warning:?“all“?matched?no?package
使用go的時候我們一般都會使用go?mode管理,下面這篇文章主要給大家介紹了關于go?mode?tidy出現報錯go:?warning:?“all“?matched?no?packages的解決方法,文中通過圖文介紹的非常詳細,需要的朋友可以參考下2022-08-08
Go語言Web編程實現Get和Post請求發(fā)送與解析的方法詳解
這篇文章主要介紹了Go語言Web編程實現Get和Post請求發(fā)送與解析的方法,結合實例形式分析了Go語言客戶端、服務器端結合實現web數據get、post發(fā)送與接收數據的相關操作技巧,需要的朋友可以參考下2017-06-06

