最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Golang中Channel的原理和使用技巧

 更新時(shí)間:2022年11月23日 08:59:21   作者:AllenWu  
Channel管道提供了一種機(jī)制,它在兩個(gè)并發(fā)執(zhí)行的協(xié)程之間進(jìn)行同步,并通過(guò)傳遞與該管道元素類型相符的值來(lái)進(jìn)行通信。本文主要介紹了Channel的原理和使用技巧,需要的可以參考一下

Channel 詳解

Channel 簡(jiǎn)要說(shuō)明

Channel(一般簡(jiǎn)寫(xiě)為 chan) 管道提供了一種機(jī)制,它在兩個(gè)并發(fā)執(zhí)行的協(xié)程之間進(jìn)行同步,并通過(guò)傳遞與該管道元素類型相符的值來(lái)進(jìn)行通信。Channel 是用來(lái)在不同的 goroutine 中交換數(shù)據(jù)的,千萬(wàn)不要把 Channel 拿來(lái)在同一個(gè) goroutine 中的不同函數(shù)之間間交換數(shù)據(jù),chan 可以理解為一個(gè)管道或者先進(jìn)先出的隊(duì)列。

Channel 類型定義

最簡(jiǎn)單形式: chan elementType,通過(guò)這個(gè)類型的值,你可以發(fā)送和接收elementType 類型的元素。Channel 是引用類型,如果將一個(gè) chan 變量賦值給另外一個(gè),則這兩個(gè)變量訪問(wèn)的是相同的 chann。

當(dāng)然,我們可以用 make 分配一個(gè)channel:var c = make(chan int)

Channel 操作符<- 和操作方式

通信操作符 <- 的箭頭指示數(shù)據(jù)流向,箭頭指向哪里,數(shù)據(jù)就流向哪里,它是一個(gè)二元操作符,可以支持任意類型,對(duì)于 channel 的操作只有4種方式:

1.創(chuàng)建 channel (通過(guò)make()函數(shù)實(shí)現(xiàn),包括無(wú)緩存 channel 和有緩存 channel);

2.向 channel 中添加數(shù)據(jù)(channel<-data);

3.從 channel 中讀取數(shù)據(jù)(data<-channel);

  • data<-channel, 從 channel 中接收數(shù)據(jù)并賦值給 data
  • <-channel,從 channel 中接收數(shù)據(jù)并丟棄

4.關(guān)閉 channel(通過(guò) close()函數(shù)實(shí)現(xiàn))

  • 讀取關(guān)閉后的無(wú)緩存通道,不管通道中是否有數(shù)據(jù),返回值都為 0 和 false。
  • 讀取關(guān)閉后的有緩存通道,將緩存數(shù)據(jù)讀取完后,再讀取返回值為 0 和 false。
  • 對(duì)于一個(gè)關(guān)閉的 channel,如果繼續(xù)向 channel 發(fā)送數(shù)據(jù),會(huì)引起 panic
  • channel 不能 close 兩次,多次 close 會(huì) panic

Channel 有無(wú)緩沖 & 同步、異步

channel 分為有緩沖 channel 和無(wú)緩沖 channel,兩種 channel 的創(chuàng)建方法如下:

var ch = make(chan int) //無(wú)緩沖 channel,等同于make(chan int ,0),是一個(gè)同步的 Channel

  • 無(wú)緩沖 channel 在讀和寫(xiě)的過(guò)程中是都會(huì)阻塞,由于阻塞的存在,所以使用 channel 時(shí)特別注意使用方法,防止死鎖和協(xié)程泄漏的產(chǎn)生。
  • 無(wú)緩沖 channel 的發(fā)送動(dòng)作一直要到有一個(gè)接收者接收這個(gè)值才算完成,否則都是阻塞著的,也就是說(shuō),發(fā)送的數(shù)據(jù)需要被讀取后,發(fā)送才會(huì)完成
  • 一般要配合 select + timeout 處理,然后再在這里添加超時(shí)時(shí)間

var ch = make(chan int,10) //有緩沖channel,緩沖大小是10,是一個(gè)異步的Channel

  • 帶緩存的 channel 實(shí)際上是一個(gè)阻塞隊(duì)列。隊(duì)列滿時(shí)寫(xiě)協(xié)程會(huì)阻塞,隊(duì)列空時(shí)讀協(xié)程阻塞。
  • 有緩沖的時(shí)候,寫(xiě)操作是寫(xiě)完之后直接返回的。相對(duì)于不帶緩存 channel,帶緩存 channel 不易造成死鎖。

Channel 各種操作導(dǎo)致阻塞和協(xié)程泄漏的場(chǎng)景

寫(xiě)操作,什么時(shí)候會(huì)被阻塞?

1.向 nil 通道發(fā)送數(shù)據(jù)會(huì)被阻塞

2.向無(wú)緩沖 channel 寫(xiě)數(shù)據(jù),如果讀協(xié)程沒(méi)有準(zhǔn)備好,會(huì)阻塞

  • 無(wú)緩沖 channel ,必須要有讀有寫(xiě),寫(xiě)了數(shù)據(jù)之后,必須要讀出來(lái),否則導(dǎo)致 channel 阻塞,從而使得協(xié)程阻塞而使得協(xié)程泄漏
  • 一個(gè)無(wú)緩沖 channel,如果每次來(lái)一個(gè)請(qǐng)求就開(kāi)一個(gè) go 協(xié)程往里面寫(xiě)數(shù)據(jù),但是一直沒(méi)有被讀取,那么就會(huì)導(dǎo)致這個(gè) chan 一直阻塞,使得寫(xiě)這個(gè) chan 的 go 協(xié)程一直無(wú)法釋放從而協(xié)程泄漏。

3.向有緩沖 channel 寫(xiě)數(shù)據(jù),如果緩沖已滿,會(huì)阻塞

有緩沖的 channel,在緩沖 buffer 之內(nèi),不讀取也不會(huì)導(dǎo)致阻塞,當(dāng)然也就不會(huì)使得協(xié)程泄漏,但是如果寫(xiě)數(shù)據(jù)超過(guò)了 buffer 還沒(méi)有讀取,那么繼續(xù)寫(xiě)的時(shí)候就會(huì)阻塞了。如果往有緩沖的 channel 寫(xiě)了數(shù)據(jù)但是一直沒(méi)有讀取就直接退出協(xié)程的話,一樣會(huì)導(dǎo)致 channel 阻塞,從而使得協(xié)程阻塞并泄漏。

讀操作,什么時(shí)候會(huì)被阻塞?

  • 從 nil 通道接收數(shù)據(jù)會(huì)被阻塞
  • 從無(wú)緩沖 channel 讀數(shù)據(jù),如果寫(xiě)協(xié)程沒(méi)有準(zhǔn)備好,會(huì)阻塞
  • 從有緩沖 channel 讀數(shù)據(jù),如果緩沖為空,會(huì)阻塞

close 操作,什么時(shí)候會(huì)被阻塞?

close channel 對(duì) channel 阻塞是沒(méi)有任何效果的,寫(xiě)了數(shù)據(jù)但是不讀,直接 close,還是會(huì)阻塞的。

Channel 各種操作對(duì)應(yīng)的狀態(tài)

  • 正常的 channel,可讀、可寫(xiě)
  • nil 的 channel,表示未初始化的狀態(tài),只進(jìn)行了聲明,或者手動(dòng)賦值為 nil
  • 已經(jīng) closed 的 channel,表示已經(jīng) close 關(guān)閉了,千萬(wàn)不要誤認(rèn)為關(guān)閉 channel 后,channel 的值是 nil

Channel 長(zhǎng)度和容量

容量(capacity)代表 Channel 容納的最多的元素的數(shù)量,代表Channel的緩存的大小。如果沒(méi)有設(shè)置容量,或者容量設(shè)置為0, 說(shuō)明 Channel 沒(méi)有緩存,長(zhǎng)度和容量的兩個(gè)函數(shù)是 cap 和 len 。

示例如下:

c := make(chan int, 100) // cap 就是 100,但是此時(shí) len 為 0
c <- 0  // len = 1, cap = 100
c <- 0  // len = 2, cap = 100
<- c    // len = 1, cap = 100

Channel 的缺點(diǎn)

Channel 的缺點(diǎn):

Channel 可能會(huì)導(dǎo)致循環(huán)阻塞或者協(xié)程泄漏,這個(gè)是最最最要重點(diǎn)關(guān)注的。

Channel 中傳遞指針會(huì)導(dǎo)致數(shù)據(jù)競(jìng)態(tài)問(wèn)題(data race/ race conditions)

Channel 中傳遞的都是數(shù)據(jù)的拷貝,可能會(huì)影響性能,但是就目前我們的機(jī)器性能來(lái)看,這點(diǎn)數(shù)據(jù)拷貝所帶來(lái)的 CPU 消耗,大多數(shù)的情況下可以忽略。

Go Channel 實(shí)現(xiàn)協(xié)程同步

channel 實(shí)現(xiàn)并發(fā)同步的說(shuō)明

channel 作為 Go 并發(fā)模型的核心思想:不要通過(guò)共享內(nèi)存來(lái)通信,而應(yīng)該通過(guò)通信來(lái)共享內(nèi)存,那么在 Go 里面,當(dāng)然也可以很方便通過(guò) channel 來(lái)實(shí)現(xiàn)協(xié)程的并發(fā)和同步了,并且 channel 本身還可以支持有緩沖和無(wú)緩沖的,通過(guò) channel + timeout 實(shí)現(xiàn)并發(fā)協(xié)程之間的同步也是常見(jiàn)的一種使用姿勢(shì)。

無(wú)緩沖 chan 示例

示例如下:

package main
import "fmt"
func main() {
     var ch = make(chan string)
     for i := 0; i < 10; i++ {
             go sum(i, i+10, ch)
     }
     for i := 0; i < 10; i++ {
             fmt.Print(<-ch)
     }
}
func sum(start, end int, ch chan string) {
     var sum int = 0
     for i := start; i < end; i++ {
             sum += i
     }
     ch <- fmt.Sprintf("Sum from %d to %d is %d\n", start, end, sum)
}

有緩沖 chan 示例

	message_chan := make(chan int, 2)

	go func() {
		time.Sleep(time.Second * 3)
		println("start recv...")
		println(<-message_chan)
		println(<-message_chan)
		println(<-message_chan)
		println("finish recv...")
	}()

	println("start send 10...")
	message_chan <- 10

	println("start send 20...")
	message_chan <- 20

	println("start send 30...")
	message_chan <- 30

	println("finish send...")

	time.Sleep(time.Second * 3)
	close(message_chan)

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

相關(guān)文章

  • 使用Go語(yǔ)言編寫(xiě)簡(jiǎn)潔代碼的最佳實(shí)踐

    使用Go語(yǔ)言編寫(xiě)簡(jiǎn)潔代碼的最佳實(shí)踐

    簡(jiǎn)潔的代碼對(duì)于創(chuàng)建可維護(hù)、可閱讀和高效的軟件至關(guān)重要,Go 是一種強(qiáng)調(diào)簡(jiǎn)單和代碼整潔的語(yǔ)言,在本文中,我們將結(jié)合代碼示例,探討編寫(xiě)簡(jiǎn)潔 Go 代碼的最佳實(shí)踐,需要的朋友可以參考下
    2023-09-09
  • Golang中的new()和make()函數(shù)本質(zhì)區(qū)別

    Golang中的new()和make()函數(shù)本質(zhì)區(qū)別

    在 Go 語(yǔ)言開(kāi)發(fā)中,new() 和 make() 是兩個(gè)容易讓開(kāi)發(fā)者感到困惑的內(nèi)建函數(shù),盡管它們都用于內(nèi)存分配,但其設(shè)計(jì)目的、適用場(chǎng)景和底層實(shí)現(xiàn)存在本質(zhì)差異,本文將通過(guò)類型系統(tǒng)、內(nèi)存模型和編譯器實(shí)現(xiàn)三個(gè)維度,深入解析這兩個(gè)函數(shù)的本質(zhì)區(qū)別,感興趣的朋友一起看看吧
    2025-02-02
  • Go高級(jí)特性探究之對(duì)象比較詳解

    Go高級(jí)特性探究之對(duì)象比較詳解

    在go語(yǔ)言中,要比較兩個(gè)對(duì)象是否完全相同,我們可以使用三種方法,這篇文章主要為大家介紹了這三種方法的具體實(shí)現(xiàn),需要的可以參考一下
    2023-06-06
  • GO語(yǔ)言創(chuàng)建錢(qián)包并遍歷錢(qián)包(wallet)的實(shí)現(xiàn)代碼

    GO語(yǔ)言創(chuàng)建錢(qián)包并遍歷錢(qián)包(wallet)的實(shí)現(xiàn)代碼

    比特幣錢(qián)包實(shí)際上是一個(gè)密鑰對(duì),當(dāng)你安裝 一個(gè)錢(qián)包應(yīng)用,或者是使用一個(gè)比特幣客戶端來(lái)生成一個(gè)新地址是,他就會(huì)為你生成一個(gè)密鑰對(duì),今天通過(guò)本文給大家分享go語(yǔ)言遍歷錢(qián)包的相關(guān)知識(shí),一起看看吧
    2021-05-05
  • Go語(yǔ)言里的new函數(shù)用法分析

    Go語(yǔ)言里的new函數(shù)用法分析

    這篇文章主要介紹了Go語(yǔ)言里的new函數(shù)用法,實(shí)例分析了new函數(shù)的功能及使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-02-02
  • golang中time包之時(shí)間間隔格式化和秒、毫秒、納秒等時(shí)間戳格式輸出的方法實(shí)例

    golang中time包之時(shí)間間隔格式化和秒、毫秒、納秒等時(shí)間戳格式輸出的方法實(shí)例

    時(shí)間和日期是我們編程中經(jīng)常會(huì)用到的,下面這篇文章主要給大家介紹了關(guān)于golang中time包之時(shí)間間隔格式化和秒、毫秒、納秒等時(shí)間戳格式輸出的方法實(shí)例,需要的朋友可以參考下
    2022-08-08
  • 使用go gin來(lái)操作cookie的講解

    使用go gin來(lái)操作cookie的講解

    今天小編就為大家分享一篇關(guān)于使用go gin來(lái)操作cookie的講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-04-04
  • victoriaMetrics庫(kù)布隆過(guò)濾器初始化及使用詳解

    victoriaMetrics庫(kù)布隆過(guò)濾器初始化及使用詳解

    這篇文章主要為大家介紹了victoriaMetrics庫(kù)布隆過(guò)濾器初始化及使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • go?mod?tidy報(bào)錯(cuò):zip:?not?a?valid?zip?file解決辦法

    go?mod?tidy報(bào)錯(cuò):zip:?not?a?valid?zip?file解決辦法

    這篇文章主要給大家介紹了關(guān)于go?mod?tidy報(bào)錯(cuò):zip:?not?a?valid?zip?file的解決辦法,go mod是進(jìn)行代碼管理,這錯(cuò)誤是因?yàn)楸镜胤种Ш瓦h(yuǎn)程分支沖突,本文通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • golang高并發(fā)的深入理解

    golang高并發(fā)的深入理解

    golang從語(yǔ)言級(jí)別上對(duì)并發(fā)提供了支持,而且在啟動(dòng)并發(fā)的方式上直接添加了語(yǔ)言級(jí)的關(guān)鍵字。下面這篇文章主要給大家介紹了關(guān)于golang高并發(fā)的相關(guān)資料,需要的朋友可以參考下
    2019-03-03

最新評(píng)論

遂溪县| 红原县| 小金县| 辽阳县| 乐平市| 根河市| 祁阳县| 通州区| 闻喜县| 蚌埠市| 奉新县| 南丰县| 大丰市| 柘荣县| 盘山县| 宜兰县| 巩留县| 普兰店市| 襄汾县| 大理市| 即墨市| 门头沟区| 北碚区| 海阳市| 额敏县| 桐柏县| 南漳县| 伽师县| 聂荣县| 昆山市| 芦山县| 赞皇县| 龙岩市| 贡嘎县| 武乡县| 连城县| 犍为县| 图木舒克市| 德令哈市| 宜城市| 六枝特区|