亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

Golang中這些channel用法你了解嗎

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

channel 是什么

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

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

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

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

巧用 nil 的 channel 通道

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

我們先來看這么一個例子

  • 創(chuàng)建兩個 channel c1, c2 ,數(shù)據類型是 struct{} ,用于占位
  • 分別開辟兩個子協(xié)程,其中子協(xié)程 1 在 2 秒之后寫入數(shù)據給到 c1,另外一個子協(xié)程 2 在 1 秒之后寫入數(shù)據給到 c2
  • 主協(xié)程循環(huán)等待阻塞讀取 c1 , c2 里面的數(shù)據,讀取后將對應的標識 ok1 / ok2 置為 true
  • 當 ok1 和 ok2 都為 true 的時候,退出循環(huán),結束程序
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 ... ")
}

運行結果如下:

2
1
program termination ...

看上去效果一切正常,若此時,我們將上述代碼中的 close(c1) 和 close(c2) 的注釋去掉,我們再查看一下結果就回是這樣的:

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

出現(xiàn)這樣的問題是什么呢?是因為我們 close channel 通道之后,若還對這個通道寫入數(shù)據會 panic,若還從這個通道讀取數(shù)據會立即返回該通道類型的零值,而不會阻塞等待數(shù)據

因此才會有上述情況,那么這個時候,我就可以很好的用好這個 nil 的 channel,咱就可以這樣來調整一下關于通道使用的情況

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

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ù)據,先去判斷通道是否關閉,若通道關閉了,那么我們直接顯示的給通道設置為 nil

這里是否會有這么一個疑問?關閉通道,通道變量不應該就變成 nil 了嗎?為什么我們還要自己去設置為 nil?

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

巧用無緩沖 channel 通道

對于無緩沖的 channel 通道,只有在對其進行接收操作的 goroutine 協(xié)程和對其進行發(fā)送操作的 goroutine 協(xié)程都存在的情況下,通信才能進行,否則單方面的操作會讓對應的 goroutine 協(xié)程陷入阻塞狀態(tài),因為該 channel 通道沒有緩沖

使用無緩沖的 channel 通道,我們可以用在如下幾個方面

1.信號傳遞

信號傳遞我們就可以用在兩個協(xié)程一對一的傳遞信號上面,當然我們也可以使用在主協(xié)程主動通知所有子協(xié)程關閉的全場景下,這就是一對多的傳遞信號,相關的 demo 可以在這期文章中有展示

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

一對一(一個發(fā)一個收)

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

2.控制同步

GO語言倡導我們不要通過共享內存來通信,而應該通過通信來共享內存,此處 channel 就是這樣設計的,當然如果需要有更高的性能,那么我們還是可以使用更加低級的GO語言原語 sync 包中的鎖機制

可以點擊查看往期文章:sync 鎖機制

巧用有緩沖 channel 通道

1.用作隊列

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

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

對于有緩沖的 channel 通道,channel 通道滿的時候,寫入數(shù)據會阻塞,讀取數(shù)據正常處理, channel 通道空的時候,寫入數(shù)據正常,讀取數(shù)據會阻塞

2.用作信號量

有緩沖的 channel 通道還可以用來計數(shù),例如我們有 15 個 job,可是目前只有 3 個 worker,那么同一時間,只會有 3 個worker 來干活,我們就可以使用通道來查看目前有多少個 worker 在工作,寫一個簡單的 demo

  • 創(chuàng)建 j 和 worker channel 通道,
  • 子協(xié)程 1 寫 15 個任務給到 j 通道中,寫完 15 個任務到 j 中便關閉自己的通道(因為后續(xù)我們需要使用 for...range 的方式讀取通道)
  • 使用 sync.WaitGroup 管控開辟的 3 個協(xié)程,模擬 3 個 工人去干活
  • 能夠從寫入數(shù)據到 worker channel 通道中,則開始干活,干完之后,從 worker channel 通道中讀出數(shù)據
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 的可以復制代碼運行一下,可以看到效果是 3 個 job 一起打印,間隔 1 秒后,又是 3 個 job 一起打印的

select 和 channel 通道如何結合使用?

1.心跳

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

2.使用 default

select ...default 這個組合就不必過多贅述了,就是在我們阻塞讀取通道數(shù)據時,若當前時間沒有從任何一個通道中讀取到數(shù)據,則默認走 default 里面的邏輯

3.超時機制

超時機制使用的也是非常頻繁的,很多時候為了方便,可能我們會使用例如<- time.After(10 * time.Second) 的方式,使用這種方式,GO 語言會維護一個最小堆,當時間到了,通道被喚醒的時候,就會從最小堆頂取出 timer 對象,再執(zhí)行 timer 中的函數(shù),執(zhí)行完畢之后,自行就會做刪除,自行就會做 GC

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

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

總結

本次演示了關于 nil channel,有緩沖 channel ,無緩沖 channel , select 如何與 channel 配合使用,上述 demo 完全可以復制下來,xdm 可以自行運行,查看效果

以上就是Golang中這些channel用法你了解嗎的詳細內容,更多關于Go channel的資料請關注腳本之家其它相關文章!

相關文章

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

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

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

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

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

    Go?mod?replace使用方法及常見問題分析

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

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

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

    Go語言七篇入門教程七GC垃圾回收三色標記

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

    golang http 連接超時和傳輸超時的例子

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

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

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

    在Go中構建并發(fā)TCP服務器

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

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

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

    go語言實現(xiàn)字符串與其它類型轉換(strconv包)

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

最新評論