欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Go語(yǔ)言中select使用詳解

 更新時(shí)間:2025年05月14日 11:02:04   作者:gopher.guo  
這篇文章主要介紹了Go語(yǔ)言中select使用的相關(guān)資料,select是Go語(yǔ)言中用于多路channel操作的控制結(jié)構(gòu),可以監(jiān)聽(tīng)多個(gè)channel的發(fā)送與接收操作,當(dāng)其中某一個(gè)可以進(jìn)行時(shí)就執(zhí)行對(duì)應(yīng)的語(yǔ)句,從而實(shí)現(xiàn)非阻塞并發(fā)通信,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下

什么是 select?

select 是 Go 中用于 多路 channel 操作 的控制結(jié)構(gòu),它可以監(jiān)聽(tīng)多個(gè) channel 的發(fā)送與接收操作,當(dāng)其中某一個(gè)可以進(jìn)行時(shí)就執(zhí)行對(duì)應(yīng)的語(yǔ)句,從而實(shí)現(xiàn)非阻塞并發(fā)通信。

基本語(yǔ)法

select {
case val := <-ch1:
    // ch1 可讀時(shí)執(zhí)行
case ch2 <- 100:
    // ch2 可寫時(shí)執(zhí)行
default:
    // 所有 channel 都阻塞時(shí)執(zhí)行(可選)
}
  • 每個(gè) case 必須是 發(fā)送(ch <- val)或接收(val := <-ch)

  • 只會(huì)執(zhí)行一個(gè)可操作的 case(如果多個(gè)都可以隨機(jī)挑一個(gè))

  • 如果都阻塞,且沒(méi)有 default,select 會(huì)阻塞等待

  • 如果包含 default,它會(huì)立即執(zhí)行,哪怕其他 case 可能之后才可操作

使用場(chǎng)景舉例

1. 監(jiān)聽(tīng)多個(gè) channel 的數(shù)據(jù)

select {
case msg1 := <-ch1:
    fmt.Println("收到 ch1:", msg1)
case msg2 := <-ch2:
    fmt.Println("收到 ch2:", msg2)
}

2. 實(shí)現(xiàn)超時(shí)機(jī)制

select {
case msg := <-ch:
    fmt.Println("收到:", msg)
case <-time.After(2 * time.Second):
    fmt.Println("超時(shí)")
}

time.After 返回一個(gè) channel,在指定時(shí)間后變?yōu)榭勺x,實(shí)現(xiàn)優(yōu)雅的 timeout。

3. 非阻塞發(fā)送或接收(default 分支)

select {
case ch <- data:
    fmt.Println("發(fā)送成功")
default:
    fmt.Println("channel 滿,放棄發(fā)送")
}

4. 檢測(cè)通道是否關(guān)閉

select {
case v, ok := <-ch:
    if !ok {
        fmt.Println("通道關(guān)閉")
    } else {
        fmt.Println("收到:", v)
    }
}

select 的行為特點(diǎn)

行為描述
隨機(jī)調(diào)度多個(gè) case 同時(shí)可用時(shí)隨機(jī)選擇一個(gè)執(zhí)行(防止饑餓)
阻塞等待所有 case 阻塞時(shí),select 自身也阻塞
default 分支所有 case 阻塞時(shí)立即執(zhí)行,避免阻塞
只選一個(gè)同時(shí)滿足多個(gè)時(shí)只執(zhí)行其中一個(gè)

與 goroutine 配合:生產(chǎn)者/消費(fèi)者模型

func producer(ch chan int) {
    for i := 0; i < 5; i++ {
        ch <- i
    }
    close(ch)
}
?
func consumer(ch chan int, done chan struct{}) {
    for {
        select {
        case val, ok := <-ch:
            if !ok {
                done <- struct{}{}
                return
            }
            fmt.Println("消費(fèi):", val)
        }
    }
}

select + for:常見(jiàn)循環(huán)寫法

for {
    select {
    case msg := <-ch:
        fmt.Println("收到:", msg)
    case <-time.After(5 * time.Second):
        fmt.Println("超時(shí)退出")
        return
    }
}

select 常見(jiàn)陷阱

陷阱描述
忘記 default 導(dǎo)致阻塞如果所有 case 阻塞,select 也阻塞
無(wú)限阻塞select 中所有 channel 永遠(yuǎn)不會(huì)可用
channel 已關(guān)閉向已關(guān)閉通道寫入會(huì) panic,應(yīng)特別小心
超時(shí)誤用使用 time.After() 時(shí),不要在循環(huán)里頻繁創(chuàng)建新 channel,否則內(nèi)存泄漏

?? 解決建議:使用 time.NewTimer,并復(fù)用 timer。

實(shí)戰(zhàn)建議

建議原因
用 select 實(shí)現(xiàn)超時(shí)控制比較優(yōu)雅且非阻塞
select + default 實(shí)現(xiàn)非阻塞通信避免 goroutine 卡死
用 select + context.Done() 控制退出在大型系統(tǒng)中更適合

例子:context 控制退出(推薦生產(chǎn)使用)

ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
?
ch := make(chan int)
?
go func() {
    time.Sleep(2 * time.Second)
    ch <- 42
}()
?
select {
case <-ctx.Done():
    fmt.Println("操作取消/超時(shí):", ctx.Err())
case val := <-ch:
    fmt.Println("接收到數(shù)據(jù):", val)
}

總結(jié)

維度說(shuō)明
功能實(shí)現(xiàn) channel 的多路復(fù)用監(jiān)聽(tīng)
優(yōu)點(diǎn)非阻塞、高效、優(yōu)雅處理通信控制
結(jié)合time.After、context、default 最佳組合
場(chǎng)景goroutine 退出、任務(wù)超時(shí)、并發(fā)協(xié)程間通信控制等

到此這篇關(guān)于Go語(yǔ)言中select使用的文章就介紹到這了,更多相關(guān)Go select詳解內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang常用庫(kù)之配置文件解析庫(kù)-viper使用詳解

    golang常用庫(kù)之配置文件解析庫(kù)-viper使用詳解

    viper 配置管理解析庫(kù),是由大神 Steve Francia 開(kāi)發(fā),他在google領(lǐng)導(dǎo)著 golang 的產(chǎn)品開(kāi)發(fā),他也是 gohugo.io 的創(chuàng)始人之一,命令行解析庫(kù) cobra 開(kāi)發(fā)者,這篇文章主要介紹了golang常用庫(kù)之配置文件解析庫(kù)-viper使用詳解,需要的朋友可以參考下
    2020-10-10
  • GO語(yǔ)言函數(shù)(func)的聲明與使用詳解

    GO語(yǔ)言函數(shù)(func)的聲明與使用詳解

    這篇文章主要介紹了GO函數(shù)(func)的聲明與使用,包括了GO語(yǔ)言函數(shù)聲明與使用,GO語(yǔ)言遞歸函數(shù),GO語(yǔ)言內(nèi)置函數(shù),GO語(yǔ)言函數(shù)defer應(yīng)用,GO語(yǔ)言函數(shù)可變長(zhǎng)度參數(shù)需要的朋友可以參考下
    2022-12-12
  • Go語(yǔ)言如何實(shí)現(xiàn)線程安全的Map

    Go語(yǔ)言如何實(shí)現(xiàn)線程安全的Map

    Go語(yǔ)言內(nèi)置的map雖然高效,但并不是線程安全的,若在多線程環(huán)境中直接操作map,可能會(huì)引發(fā)并發(fā)寫入的錯(cuò)誤,下面我們就來(lái)看看如何實(shí)現(xiàn)線程安全的Map吧
    2024-11-11
  • golang模擬TCP粘包和拆包

    golang模擬TCP粘包和拆包

    粘包是指在發(fā)送多個(gè)小的數(shù)據(jù)包時(shí),接收端會(huì)將這些數(shù)據(jù)包合并成一個(gè)數(shù)據(jù)包接收,拆包是指發(fā)送的數(shù)據(jù)包在傳輸過(guò)程中被分割成多個(gè)小包,下面我們來(lái)看看go如何模擬TCP粘包和拆包吧
    2024-12-12
  • Go語(yǔ)言學(xué)習(xí)網(wǎng)絡(luò)編程與Http教程示例

    Go語(yǔ)言學(xué)習(xí)網(wǎng)絡(luò)編程與Http教程示例

    這篇文章主要為大家介紹了Go語(yǔ)言學(xué)習(xí)網(wǎng)絡(luò)編程與Http教程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Go中使用操作符進(jìn)行數(shù)學(xué)運(yùn)算的示例代碼

    Go中使用操作符進(jìn)行數(shù)學(xué)運(yùn)算的示例代碼

    在編程中有效地執(zhí)行數(shù)學(xué)運(yùn)算是一項(xiàng)需要開(kāi)發(fā)的重要技能,本文主要介紹了Go中使用操作符進(jìn)行數(shù)學(xué)運(yùn)算的示例代碼,具有一定的參考價(jià)值,感興趣的可以了解一下
    2023-10-10
  • Go語(yǔ)言Http?Server框架實(shí)現(xiàn)一個(gè)簡(jiǎn)單的httpServer

    Go語(yǔ)言Http?Server框架實(shí)現(xiàn)一個(gè)簡(jiǎn)單的httpServer

    這篇文章主要為大家介紹了Go語(yǔ)言Http?Server框架實(shí)現(xiàn)一個(gè)簡(jiǎn)單的httpServer抽象,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • Go 中燒腦的接口及空接口

    Go 中燒腦的接口及空接口

    在Go語(yǔ)言的實(shí)際編程中,幾乎所有的數(shù)據(jù)結(jié)構(gòu)都圍繞接口展開(kāi),接口是Go語(yǔ)言中所有數(shù)據(jù)結(jié)構(gòu)的核心,這篇文章主要介紹了Go 中燒腦的接口,需要的朋友可以參考下
    2024-02-02
  • Golang WaitGroup實(shí)現(xiàn)原理解析

    Golang WaitGroup實(shí)現(xiàn)原理解析

    WaitGroup是Golang并發(fā)的兩種方式之一,一個(gè)是Channel,另一個(gè)是WaitGroup,下面這篇文章主要給大家介紹了關(guān)于golang基礎(chǔ)之waitgroup用法以及使用要點(diǎn)的相關(guān)資料,需要的朋友可以參考下
    2023-02-02
  • 解讀rand.Seed(time.Now().UnixNano())的作用及說(shuō)明

    解讀rand.Seed(time.Now().UnixNano())的作用及說(shuō)明

    這篇文章主要介紹了關(guān)于rand.Seed(time.Now().UnixNano())的作用及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。
    2023-03-03

最新評(píng)論