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

Golang中這些channel用法你了解嗎

 更新時(shí)間:2023年08月30日 09:44:21   作者:阿兵云原生  
channel?是GO語(yǔ)言中一種特殊的類(lèi)型,是連接并發(fā)goroutine的管道,這篇文章主要來(lái)和大家分享一下關(guān)于?nil?channel?通道,有緩沖通道,無(wú)緩沖通道的常用方法以及巧妙使用的方式,希望對(duì)大家有所幫助

channel 是什么

channel 是GO語(yǔ)言中一種特殊的類(lèi)型,是連接并發(fā)goroutine的管道

channel 通道是可以讓一個(gè) goroutine 協(xié)程發(fā)送特定值到另一個(gè) goroutine 協(xié)程的通信機(jī)制

關(guān)于 channel 的原理,channel通道需要注意的地方,之前有分享過(guò),可以查看如下文章

本次,我們主要分享的是關(guān)于 nil channel 通道,有緩沖通道,無(wú)緩沖通道 的常用方法以及巧妙使用的方式

巧用 nil 的 channel 通道

平日里使用的 channel 通道都是使用無(wú)緩沖,或者有緩沖的 channel 通道,或許使用為 nil 的 channel 通道還是比較少,甚至都不知道如何去使用 nil 的 channel 通道

我們先來(lái)看這么一個(gè)例子

  • 創(chuàng)建兩個(gè) channel c1, c2 ,數(shù)據(jù)類(lèi)型是 struct{} ,用于占位
  • 分別開(kāi)辟兩個(gè)子協(xié)程,其中子協(xié)程 1 在 2 秒之后寫(xiě)入數(shù)據(jù)給到 c1,另外一個(gè)子協(xié)程 2 在 1 秒之后寫(xiě)入數(shù)據(jù)給到 c2
  • 主協(xié)程循環(huán)等待阻塞讀取 c1 , c2 里面的數(shù)據(jù),讀取后將對(duì)應(yīng)的標(biāo)識(shí) ok1 / ok2 置為 true
  • 當(dāng) ok1 和 ok2 都為 true 的時(shí)候,退出循環(huán),結(jié)束程序
func main() {
    c1, c2 := make(chan struct{}), make(chan struct{})
    go func() {
        time.Sleep(time.Second * 2)
        c1 <- struct{}{}
        //close(c1)
    }()
    go func() {
        time.Sleep(time.Second * 1)
        c2 <- struct{}{}
       // close(c2)
    }()
    var (
        ok1 bool
        ok2 bool
    )
    for {
        select {
        case <-c1:
                ok1 = true
                fmt.Println("1")
        case <-c2:
                ok2 = true
                fmt.Println("2")
        }
        if ok1 && ok2 {
                break
        }
    }
    fmt.Println("program termination ... ")
}

運(yùn)行結(jié)果如下:

2
1
program termination ...

看上去效果一切正常,若此時(shí),我們將上述代碼中的 close(c1) 和 close(c2) 的注釋去掉,我們?cè)俨榭匆幌陆Y(jié)果就回是這樣的:

...
2
2
2
1
program termination ...

出現(xiàn)這樣的問(wèn)題是什么呢?是因?yàn)槲覀?close channel 通道之后,若還對(duì)這個(gè)通道寫(xiě)入數(shù)據(jù)會(huì) panic,若還從這個(gè)通道讀取數(shù)據(jù)會(huì)立即返回該通道類(lèi)型的零值,而不會(huì)阻塞等待數(shù)據(jù)

因此才會(huì)有上述情況,那么這個(gè)時(shí)候,我就可以很好的用好這個(gè) nil 的 channel,咱就可以這樣來(lái)調(diào)整一下關(guān)于通道使用的情況

修改為,從通道中讀取數(shù)據(jù)時(shí),先判斷通道是否已經(jīng)關(guān)閉,若關(guān)閉則將通道設(shè)置為 nil,若未關(guān)閉,則打印我們從通道中讀取的數(shù)據(jù)(此處模擬直接打印一個(gè)固定的值)

for {
    select {
    case _, ok := <-c1:
        if !ok {
            c1 = nil
        }else{
            fmt.Println("1")
        }
    case _, ok := <-c2:
        if !ok {
            c2 = nil
        }else{
            fmt.Println("2")
        }
    }
    if c1 == nil && c2 == nil {
            break
    }
}

這種時(shí)候,我們就知道對(duì)于從通道中讀取數(shù)據(jù),先去判斷通道是否關(guān)閉,若通道關(guān)閉了,那么我們直接顯示的給通道設(shè)置為 nil

這里是否會(huì)有這么一個(gè)疑問(wèn)?關(guān)閉通道,通道變量不應(yīng)該就變成 nil 了嗎?為什么我們還要自己去設(shè)置為 nil?

實(shí)際上這就是我們對(duì)于通道的基礎(chǔ)知識(shí)不扎實(shí)了,關(guān)閉通道后,通道本身并不會(huì)變?yōu)?nil。通道變量仍然持有通道的地址,只是通道的狀態(tài)變?yōu)榱艘殃P(guān)閉

巧用無(wú)緩沖 channel 通道

對(duì)于無(wú)緩沖的 channel 通道,只有在對(duì)其進(jìn)行接收操作的 goroutine 協(xié)程和對(duì)其進(jìn)行發(fā)送操作的 goroutine 協(xié)程都存在的情況下,通信才能進(jìn)行,否則單方面的操作會(huì)讓對(duì)應(yīng)的 goroutine 協(xié)程陷入阻塞狀態(tài),因?yàn)樵?channel 通道沒(méi)有緩沖

使用無(wú)緩沖的 channel 通道,我們可以用在如下幾個(gè)方面

1.信號(hào)傳遞

信號(hào)傳遞我們就可以用在兩個(gè)協(xié)程一對(duì)一的傳遞信號(hào)上面,當(dāng)然我們也可以使用在主協(xié)程主動(dòng)通知所有子協(xié)程關(guān)閉的全場(chǎng)景下,這就是一對(duì)多的傳遞信號(hào),相關(guān)的 demo 可以在這期文章中有展示

GO 語(yǔ)言的并發(fā)模式

一對(duì)一(一個(gè)發(fā)一個(gè)收)

一對(duì)多(一個(gè)發(fā)多個(gè)收,此處可以是 協(xié)程 1 close 掉 通道,那么 多個(gè)協(xié)程默認(rèn)都能夠讀取到通道的值是零值,此時(shí)多個(gè)子協(xié)程就可以根據(jù)通道的關(guān)閉狀態(tài)來(lái)處理后續(xù)的邏輯)

2.控制同步

GO語(yǔ)言倡導(dǎo)我們不要通過(guò)共享內(nèi)存來(lái)通信,而應(yīng)該通過(guò)通信來(lái)共享內(nèi)存,此處 channel 就是這樣設(shè)計(jì)的,當(dāng)然如果需要有更高的性能,那么我們還是可以使用更加低級(jí)的GO語(yǔ)言原語(yǔ) sync 包中的鎖機(jī)制

可以點(diǎn)擊查看往期文章:sync 鎖機(jī)制

巧用有緩沖 channel 通道

1.用作隊(duì)列

用作隊(duì)列應(yīng)該是比較好理解的,隊(duì)列先入先出 FIFO,給 channel 通道設(shè)置明確的緩沖區(qū),例如 ch:=make(chan int, 10)

多個(gè)協(xié)程就可以異步的并發(fā)處理該隊(duì)列,由于有緩沖的 channel 通道中有一定的容量,因此,對(duì)于協(xié)程讀取通道中數(shù)據(jù)時(shí),存在阻塞的情況相對(duì)無(wú)緩沖的通道來(lái)說(shuō)就會(huì)少很多,相應(yīng)的在一定程度上就提升了性能

對(duì)于有緩沖的 channel 通道,channel 通道滿(mǎn)的時(shí)候,寫(xiě)入數(shù)據(jù)會(huì)阻塞,讀取數(shù)據(jù)正常處理, channel 通道空的時(shí)候,寫(xiě)入數(shù)據(jù)正常,讀取數(shù)據(jù)會(huì)阻塞

2.用作信號(hào)量

有緩沖的 channel 通道還可以用來(lái)計(jì)數(shù),例如我們有 15 個(gè) job,可是目前只有 3 個(gè) worker,那么同一時(shí)間,只會(huì)有 3 個(gè)worker 來(lái)干活,我們就可以使用通道來(lái)查看目前有多少個(gè) worker 在工作,寫(xiě)一個(gè)簡(jiǎn)單的 demo

  • 創(chuàng)建 j 和 worker channel 通道,
  • 子協(xié)程 1 寫(xiě) 15 個(gè)任務(wù)給到 j 通道中,寫(xiě)完 15 個(gè)任務(wù)到 j 中便關(guān)閉自己的通道(因?yàn)楹罄m(xù)我們需要使用 for...range 的方式讀取通道)
  • 使用 sync.WaitGroup 管控開(kāi)辟的 3 個(gè)協(xié)程,模擬 3 個(gè) 工人去干活
  • 能夠從寫(xiě)入數(shù)據(jù)到 worker channel 通道中,則開(kāi)始干活,干完之后,從 worker channel 通道中讀出數(shù)據(jù)
func main() {
    j := make(chan int, 15)
    worker := make(chan int, 3)
    go func() {
        for i := 0; i < 15; i++ {
            j <- i
        }
        close(j)
    }()
    var wg sync.WaitGroup
    for job := range j {
        wg.Add(1)
        go func(job int) {
            defer wg.Done()
            worker <- job
            // 模擬干活
            fmt.Println("正在執(zhí)行 job : ", job)
            time.Sleep(time.Second * 1)
            <-worker
        }(job)
    }
    wg.Wait()
    fmt.Println("program termination ... ")
}

感興趣的 xdm 的可以復(fù)制代碼運(yùn)行一下,可以看到效果是 3 個(gè) job 一起打印,間隔 1 秒后,又是 3 個(gè) job 一起打印的

select 和 channel 通道如何結(jié)合使用?

1.心跳

func main() {
    h := time.NewTicker(2 * time.Second)
    defer h.Stop()
    for {
        select {
        case <-h.C:
            // 模擬處理心跳
            fmt.Println("hhh")
        }
    }
}

2.使用 default

select ...default 這個(gè)組合就不必過(guò)多贅述了,就是在我們阻塞讀取通道數(shù)據(jù)時(shí),若當(dāng)前時(shí)間沒(méi)有從任何一個(gè)通道中讀取到數(shù)據(jù),則默認(rèn)走 default 里面的邏輯

3.超時(shí)機(jī)制

超時(shí)機(jī)制使用的也是非常頻繁的,很多時(shí)候?yàn)榱朔奖悖赡芪覀儠?huì)使用例如<- time.After(10 * time.Second) 的方式,使用這種方式,GO 語(yǔ)言會(huì)維護(hù)一個(gè)最小堆,當(dāng)時(shí)間到了,通道被喚醒的時(shí)候,就會(huì)從最小堆頂取出 timer 對(duì)象,再執(zhí)行 timer 中的函數(shù),執(zhí)行完畢之后,自行就會(huì)做刪除,自行就會(huì)做 GC

可是在上述這種方式使用比較多的時(shí)候,會(huì)給程序帶來(lái) GC 的壓力,我們完全可以入如下方式來(lái)實(shí)現(xiàn)超時(shí)機(jī)制,顯示的去做 GC

func main() {
    c := time.NewTimer(10 * time.Second)
    defer c.Stop()
    for {
        select {
        case <-c.C:
            fmt.Println("program overtime ")
            return
        }
    }
}

總結(jié)

本次演示了關(guān)于 nil channel,有緩沖 channel ,無(wú)緩沖 channel , select 如何與 channel 配合使用,上述 demo 完全可以復(fù)制下來(lái),xdm 可以自行運(yùn)行,查看效果

以上就是Golang中這些channel用法你了解嗎的詳細(xì)內(nèi)容,更多關(guān)于Go channel的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 一文詳解Golang連接kafka的基本操作

    一文詳解Golang連接kafka的基本操作

    這篇文章主要為大家詳細(xì)介紹了Golang中連接kafka的基本操作的相關(guān)知識(shí),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2025-03-03
  • go?zero微服務(wù)實(shí)戰(zhàn)性能優(yōu)化極致秒殺

    go?zero微服務(wù)實(shí)戰(zhàn)性能優(yōu)化極致秒殺

    這篇文章主要為大家介紹了go-zero微服務(wù)實(shí)戰(zhàn)性能優(yōu)化極致秒殺功能實(shí)現(xiàn),有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • Go?mod?replace使用方法及常見(jiàn)問(wèn)題分析

    Go?mod?replace使用方法及常見(jiàn)問(wèn)題分析

    這篇文章主要為大家介紹了Go?mod?replace使用方法及常見(jiàn)問(wèn)題分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-08-08
  • Go使用Weighted實(shí)現(xiàn)資源管理

    Go使用Weighted實(shí)現(xiàn)資源管理

    這篇文章主要介紹了Go?語(yǔ)言中的?Weighted?并發(fā)原語(yǔ),包括?Weighted?的基本使用方法、實(shí)現(xiàn)原理、使用注意事項(xiàng)等內(nèi)容,感興趣的小伙伴可以了解一下
    2023-06-06
  • Go語(yǔ)言七篇入門(mén)教程七GC垃圾回收三色標(biāo)記

    Go語(yǔ)言七篇入門(mén)教程七GC垃圾回收三色標(biāo)記

    這篇文章主要為大家介紹了Go語(yǔ)言教程關(guān)于GC垃圾回收三色標(biāo)記的示例詳解,本篇文章是Go語(yǔ)言七篇入門(mén)教程系列文章,有需要的朋友可以借鑒參考下,希望能夠有所幫助
    2021-11-11
  • golang http 連接超時(shí)和傳輸超時(shí)的例子

    golang http 連接超時(shí)和傳輸超時(shí)的例子

    今天小編就為大家分享一篇golang http 連接超時(shí)和傳輸超時(shí)的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-07-07
  • go判斷文件夾是否存在并創(chuàng)建的實(shí)例

    go判斷文件夾是否存在并創(chuàng)建的實(shí)例

    這篇文章主要介紹了go判斷文件夾是否存在,并創(chuàng)建的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • 在Go中構(gòu)建并發(fā)TCP服務(wù)器

    在Go中構(gòu)建并發(fā)TCP服務(wù)器

    今天小編就為大家分享一篇關(guān)于在Go中構(gòu)建并發(fā)TCP服務(wù)器的文章,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2018-10-10
  • Go語(yǔ)言中并發(fā)的工作原理

    Go語(yǔ)言中并發(fā)的工作原理

    本文詳細(xì)講解了Go語(yǔ)言中并發(fā)的工作原理,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • go語(yǔ)言實(shí)現(xiàn)字符串與其它類(lèi)型轉(zhuǎn)換(strconv包)

    go語(yǔ)言實(shí)現(xiàn)字符串與其它類(lèi)型轉(zhuǎn)換(strconv包)

    strconv包是Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)的一部分,主要提供字符串與基本數(shù)據(jù)類(lèi)型之間的轉(zhuǎn)換功能,使用strconv包可以方便地在不同類(lèi)型之間進(jìn)行轉(zhuǎn)換,滿(mǎn)足日常編程中的需求,感興趣的可以了解一下
    2024-10-10

最新評(píng)論