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

Go語言通道之無緩沖通道與緩沖通道詳解

 更新時間:2023年06月18日 17:11:43   作者:香吧香  
通道是一種特殊的數(shù)據結構,可以在協(xié)程之間進行傳遞數(shù)據,從而實現(xiàn)協(xié)程之間的通信和同步,本文就來和大家講講Go語言通道中的無緩沖通道與緩沖通道吧

1.通道定義  

在多個協(xié)程之間進行通信和管理,可以使用 Go 語言提供的通道(Channel)類型。通道是一種特殊的數(shù)據結構,可以在協(xié)程之間進行傳遞數(shù)據,從而實現(xiàn)協(xié)程之間的通信和同步。多個協(xié)程可以同時讀寫同一個通道,通過通道來進行數(shù)據的傳遞和共享。

通道遵循先入先出(First In First Out)的原則,保證收發(fā)數(shù)據的順序。通道是一個特殊的數(shù)據類型,在使用之前必須定義和創(chuàng)建通道變量,定義通道的語法如下:

var name chan type

語法格式說明如下:

1)var是Go語言關鍵字,用于定義變量。

2)name是通道變量名稱,可自行命名。

3)chan是Go語言關鍵字,將變量定義為通道類型。

4)type是通道存放的數(shù)據類型。

通道定義之后,還需要使用關鍵字make創(chuàng)建通道,通道的創(chuàng)建語法如下:

name := make(chan type, num)

語法格式說明如下:

1)name是通道變量名稱,可自行命名。

2)make是Go語言關鍵字,用于創(chuàng)建通道。

3)chan type的chan是Go語言關鍵字,type是通道能存放的數(shù)據類型。

4)num是通道存放數(shù)據的數(shù)量上限。

在實際編程中,我們直接使用關鍵字make創(chuàng)建通道即可使用,這樣能省去定義通道的過程,示例代碼如下:

// 定義和創(chuàng)建通道
    var ch chan string
    ch = make(chan string)
    // 直接創(chuàng)建通道,無須定義
    ch := make(chan string)

通道創(chuàng)建之后,使用通道完成寫入和讀取數(shù)據操作。在通道里面寫入和讀取數(shù)據需要由<-操作符實現(xiàn),使用說明如下:

// 構建通道
    ch := make(chan string)
    // 往通道寫入數(shù)據
    ch <- "Hello"
    // 從通道獲取數(shù)據,賦予變量s
    s := <- ch

2.無緩沖通道

無緩沖通道是 Go 語言中一種常見的通道類型,也稱為同步通道或阻塞通道。無緩沖通道的特點是在發(fā)送和接收數(shù)據時,必須有另外一個協(xié)程同時進行相反的操作,否則會阻塞當前協(xié)程。 具體來說,無緩沖通道的特點如下:

  • 發(fā)送和接收操作是同步的,即發(fā)送操作必須等待接收操作完成后才能繼續(xù)執(zhí)行,接收操作也必須等待發(fā)送操作完成后才能繼續(xù)執(zhí)行。
  • 無緩沖通道的容量為 0,即只有在發(fā)送和接收操作同時進行時才能傳遞數(shù)據,否則會阻塞當前協(xié)程。
  • 無緩沖通道的數(shù)據傳遞是按照先進先出的順序進行的,即發(fā)送的數(shù)據會按照發(fā)送的順序被接收。 無緩沖通道可以用于協(xié)程之間的同步和通信,例如在生產者和消費者模式中,可以使用無緩沖通道來傳遞數(shù)據,從而保證生產者和消費者之間的同步和互斥。同時,無緩沖通道的使用也可以避免數(shù)據競爭問題,從而提高程序的安全性和可靠性。

通道是通過關鍵字make創(chuàng)建的,在創(chuàng)建過程中,如果沒有設置參數(shù)num,則視為創(chuàng)建無緩沖通道。無緩沖通道(Unbuffered Channel)是指在獲取數(shù)據之前沒有能力保存數(shù)據的通道,這種類型的通道要求兩個Goroutine同時處于執(zhí)行狀態(tài)才能完成寫入和獲取操作。

如果兩個Goroutine沒有同時準備,某一個Goroutine執(zhí)行寫入或獲取操作將會處于阻塞等待狀態(tài),另一個Goroutine無法執(zhí)行寫入或獲取操作,程序將會提示異常,這種類型的通道執(zhí)行寫入和獲取的交互行為是同步,任意一個操作都無法離開另一個操作單獨存在。

當我們使用無緩沖通道的時候,必須注意通道變量的操作,確保程序中有兩個或兩個以上的Goroutine同時執(zhí)行通道的讀寫操作,讀寫操作必須是一讀一寫,不能只讀不寫或只寫不讀,示例如下:

// 只寫入數(shù)據,不讀取
    ch := make(chan string)
    ch <- "Tom"
    fmt.Println("wait goroutine")
    // 只讀取數(shù)據,不寫入
    ch := make(chan string)
    <- ch
    fmt.Println("wait goroutine")

通道數(shù)據只寫入不讀取或者只讀取不寫入都會提示fatal error: all goroutines are asleep–deadlock異常,如果需要實現(xiàn)通道數(shù)據獲取超時檢測,可以使用關鍵字select實現(xiàn)。

如果程序中僅有一個Goroutine,使用通道讀寫數(shù)據也會導致異常,比如在主函數(shù)main()中對通道寫入數(shù)據,再讀取通道數(shù)據,示例如下:

package main
    import (
        "fmt"
    )
    func main() {
        // 構建通道
        ch := make(chan string)
        // 寫入通道數(shù)據
        ch <- "Tom"
        // 讀取通道數(shù)據
        <-ch
        fmt.Println("wait goroutine")
    }

如果在發(fā)送和接收數(shù)據時出現(xiàn)異常,則會引發(fā)程序異常。例如,如果我們在發(fā)送數(shù)據之前關閉通道,則會引發(fā)一個運行時異常。為了避免這種情況的發(fā)生,我們可以使用 defer 語句在函數(shù)退出之前關閉通道。例如:

func main() {
    ch := make(chan int)
    defer close(ch) // 使用 defer 關閉通道
    go func() {
        fmt.Println("開始發(fā)送消息...")
        ch <- 1
        fmt.Println("消息發(fā)送完成。")
    }()
    fmt.Println("開始接收消息...")
    msg := <-ch
    fmt.Printf("接收到的消息是:%d\n", msg)
    fmt.Println("消息接收完成。")
}

3.帶緩沖通道

帶緩沖通道(Buffered Channel)是在被獲取前能存儲一個或者多個數(shù)據的通道,這種類型的通道并不強制要求Goroutine之間必須同時完成寫入和獲取。當通道中沒有數(shù)據的時候,獲取動作才會阻塞;當通道沒有可用緩沖區(qū)存儲數(shù)據的時候,寫入動作才會阻塞。

在無緩沖通道的基礎上,只要為通道增加一個有限大小的存儲空間就能形成帶緩沖通道。帶緩沖通道在寫入時無須等待獲取即可再次執(zhí)行下一輪寫入,并且不會發(fā)生阻塞,只有當存儲空間滿了才會發(fā)生阻塞。同理,如果帶緩沖通道中有數(shù)據,獲取時將不會發(fā)生阻塞,直到通道中沒有數(shù)據可讀時,通道才會阻塞。

從通道的定義角度分析,帶緩沖和無緩沖通道的區(qū)別在于參數(shù)num。創(chuàng)建通道的時候,如果沒有設置參數(shù)num,則默認參數(shù)值為0,通道為無緩沖通道,所以寫入和獲取數(shù)據必須同時進行才不會因阻塞而異常;如果參數(shù)num大于0,則寫入和獲取數(shù)據無須同步執(zhí)行,因為通道有足夠的空間存放數(shù)據。

由于帶緩沖通道沒有讀寫同步限制,我們可以在同一個Goroutine中執(zhí)行多次寫入和獲取操作,具體示例如下:

package main
    import "fmt"
    func main() {
        // 創(chuàng)建一個3個元素緩沖大小的整型通道
        ch := make(chan int, 3)
        // 查看當前通道的大小
        fmt.Println(len(ch))
        // 發(fā)送3個整型元素到通道
        for i := 0; i < 3; i++ {
             ch <- i
        }
        // 查看當前通道的大小
        fmt.Println(len(ch))
        for i := 0; i < 3; i++ {
             fmt.Println(<-ch)
        }
        // 查看當前通道的大小
        fmt.Println(len(ch))
        // 查看當前通道的容量
        fmt.Println(cap(ch))
    }

上述代碼的說明如下:

1)通過for執(zhí)行了3次循環(huán),每次循環(huán)將變量i寫入通道,然后通過3次循環(huán)從通道獲取數(shù)據并輸出。

2)通道寫入和讀取數(shù)據的時候,使用len()函數(shù)獲取通道已有的數(shù)據量,判斷當前通道存儲的數(shù)據量是否達到上限,這樣可以防止程序在運行時提示異常。

3)使用cap()函數(shù)能獲取通道的容量大小,即獲取創(chuàng)建通道m(xù)ake()的參數(shù)num的大小。帶緩沖通道在很多特性上和無緩沖通道類似,無緩沖通道可以看作長度為0的帶緩沖通道。

根據這個特性,帶緩沖通道在下列情況下會發(fā)生阻塞:

1)帶緩沖通道的存儲數(shù)據達到上限時,再次寫入數(shù)據將發(fā)生阻塞而導致異常。

2)帶緩沖通道沒有存儲數(shù)據時,獲取數(shù)據將發(fā)生阻塞而導致異常。

Go語言為什么對通道要限制長度?因為多個Goroutine之間使用通道必然存在寫入和獲取操作,這種模式類型的典型例子為生產者消費者模式。如果不限制通道長度,當寫入數(shù)據速度大于獲取速度,內存將不斷膨脹直到應用崩潰。因此,限制通道的長度有利于約束數(shù)據生產速度,生產數(shù)據量必須在數(shù)據消費速度+通道長度的范圍內,這樣才能正常地處理數(shù)據。

到此這篇關于Go語言通道之無緩沖通道與緩沖通道詳解的文章就介紹到這了,更多相關Go通道內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Go 協(xié)程超時控制的實現(xiàn)

    Go 協(xié)程超時控制的實現(xiàn)

    本文主要介紹了Go 協(xié)程超時控制的實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-08-08
  • 深入理解Golang中指針的用途與技巧

    深入理解Golang中指針的用途與技巧

    在 Go 語言中,指針是一種重要的概念,了解和正確使用指非常關鍵,因此本文小編就來和大家講講Golang 中指針的概念與用法,希望對大家有所幫助
    2023-05-05
  • Golang函數(shù)式編程深入分析實例

    Golang函數(shù)式編程深入分析實例

    習慣與函數(shù)式編程語言的開發(fā)者,會認為for循環(huán)和if判斷語句是冗長的代碼,通過使用map和filter處理集合元素讓代碼更可讀。本文介紹Go閉包實現(xiàn)集合轉換和過濾功能
    2023-01-01
  • Go語言--切片(Slice)詳解

    Go語言--切片(Slice)詳解

    這篇文章主要介紹了Go語言--切片(Slice),Go 語言切片是對數(shù)組的抽象,下面文章小編將為大家詳細介紹該內容,需要的朋友可以參考下,希望對你有所幫助
    2021-10-10
  • Golang學習之內存逃逸分析

    Golang學習之內存逃逸分析

    內存逃逸分析是go的編譯器在編譯期間,根據變量的類型和作用域,確定變量是堆上還是棧上。本文將帶大家分析一下Golang中的內存逃逸,需要的可以了解一下
    2023-01-01
  • golang return省略用法說明

    golang return省略用法說明

    這篇文章主要介紹了golang return省略用法說明,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • golang使用接口進行靈活緩存

    golang使用接口進行靈活緩存

    緩存是編程中一種常見的技術,通過存儲昂貴的計算或?IO?結果來快速查找,從而提高性能,本文將介紹一下Go的接口如何幫助構建靈活、可擴展的緩存,感興趣的可以了解下
    2023-09-09
  • Golang 刪除文件并遞歸刪除空目錄的操作

    Golang 刪除文件并遞歸刪除空目錄的操作

    這篇文章主要介紹了Golang 刪除文件并遞歸刪除空目錄的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04
  • golang 函數(shù)以及函數(shù)和方法的詳解及區(qū)別

    golang 函數(shù)以及函數(shù)和方法的詳解及區(qū)別

    這篇文章主要介紹了golang 函數(shù)以及函數(shù)和方法的區(qū)別的相關資料,需要的朋友可以參考下
    2017-05-05
  • go-kit組件使用hystrix中間件的操作

    go-kit組件使用hystrix中間件的操作

    這篇文章主要介紹了go-kit組件使用hystrix中間件的操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04

最新評論