Go語(yǔ)言中的通道channel詳情
一、Go語(yǔ)言通道基礎(chǔ)概念
1.channel產(chǎn)生背景
線程之間進(jìn)行通信的時(shí)候,會(huì)因?yàn)橘Y源的爭(zhēng)奪而產(chǎn)生竟態(tài)問(wèn)題,為了保證數(shù)據(jù)交換的正確性,必須使用互斥量給內(nèi)存進(jìn)行加鎖,go語(yǔ)言并發(fā)的模型是CSP,提倡通過(guò)通信共享內(nèi)存,而不是通過(guò)共享內(nèi)存而實(shí)現(xiàn)通信,通道恰巧滿足這種需求。
2.channel工作方式
channel類(lèi)似與一個(gè)隊(duì)列,滿足先進(jìn)先出的規(guī)則,嚴(yán)格保證收發(fā)數(shù)據(jù)的順序,每一個(gè)通道只能通 過(guò)固定類(lèi)型的數(shù)據(jù)如果通道進(jìn)行大型結(jié)構(gòu)體、字符串的傳輸,可以將對(duì)應(yīng)的指針傳進(jìn)去,盡量的節(jié)省空間
二、通道使用語(yǔ)法
1.通道的聲明與初始化
?? ?//定義一個(gè)通道對(duì)象使用,其中int可以換為自己需要的類(lèi)型 ?? ?var a chan int ? ?? ?//初始化只有一個(gè)位置的通道(第一個(gè)參數(shù)代表通道類(lèi)型,第二個(gè)參數(shù)代表通道有幾個(gè)位置) ?? ?//位置存滿后新的數(shù)據(jù)將存不進(jìn)來(lái)(阻塞) ?? ?a = make(chan int,1)
2.將數(shù)據(jù)放入通道內(nèi)
- 取出數(shù)據(jù)使用操作符 <-操作符右是輸入變量,操作符左是通道代表數(shù)據(jù)流入通道內(nèi)
代碼如下:
? ?// 聲明一個(gè)通道 ?? ?var a chan int ?? ??? ?a <- 5
3.從通道內(nèi)取出數(shù)據(jù)
- 取出數(shù)據(jù)也使用操作符 <-操作符右是通道,操作符左是接受變量
代碼如下:
?//聲明一個(gè)通道類(lèi)型
?? ?var a chan int
?? ?fmt.Println("未初始化的通道", a)
?? ?a = make(chan int)
?? ?// wg.Add(1)
?? ?go func(a chan int) {
?? ??? ?// defer wg.Done()
?? ??? ?for {
?? ??? ??? ?x := <-a
?? ??? ??? ?fmt.Println("接收到了數(shù)據(jù):", x)
?? ??? ?}
?? ?}(a)4.關(guān)閉通道close
如果通道重復(fù)關(guān)閉或者關(guān)閉一個(gè)沒(méi)有初始化的通道就會(huì)拋出錯(cuò)誤
?close(a)//a為待關(guān)閉的通道
在并發(fā)函數(shù)中一次關(guān)閉通道代碼如下:
// 互斥鎖對(duì)象
var once sync.Once
//并發(fā)函數(shù)
//這個(gè)函數(shù)的目的是將a通道內(nèi)數(shù)據(jù)乘以10發(fā)送到通道b內(nèi)
func f2(a <-chan int, b chan<- int) {
?? ?defer wg.Done()
?? ?for {
?? ??? ?x, ok := <-a
?? ??? ?if !ok {
?? ??? ??? ?break
?? ??? ?}
?? ??? ?fmt.Println(x)
?? ??? ?b <- x * 10
?? ?}
?? ?// 確保b通道只關(guān)閉一次
?? ?once.Do(func() {
?? ??? ?close(b)
?? ?})
}三、單項(xiàng)通道及通道的狀態(tài)分析
1.單項(xiàng)輸出通道
?? ?var b <-chan int
2.單項(xiàng)輸入通道
?? ?var b chan<- int
示例函數(shù):
//單項(xiàng)通道一般做函數(shù)參數(shù),作為一種規(guī)范防止通道混用
//此函數(shù)完成的功能是將a內(nèi)的數(shù)據(jù)乘以10放入通道b內(nèi)
func f2(a <-chan int, b chan<- int) {
?? ?for {
?? ??? ?x, ok := <-a
?? ??? ?if !ok {
?? ??? ??? ?break
?? ??? ?}
?? ??? ?fmt.Println(x)
?? ??? ?b <- x * 10
?? ?}
}3.通道的狀態(tài)
| channel | nil未初始化 | 空通道 | 滿通道 | 非空 |
|---|---|---|---|---|
| 接收 | 阻塞 | 阻塞 | 接收值 | 接收值 |
| 發(fā)送 | 阻塞 | 發(fā)送值 | 阻塞 | 發(fā)送值 |
| 關(guān)閉 | panic | 關(guān)閉成功 | 關(guān)閉成功 | 關(guān)閉成功 |
| 關(guān)閉后返回的數(shù)據(jù) | panic | 返回0值 | 數(shù)據(jù)讀完后返回零值 | 數(shù)據(jù)讀完返回零值 |
四、通道死鎖原因分析
注意以下情況:
在使用通道的時(shí)候,從以上表格可知有時(shí)會(huì)進(jìn)入阻塞狀態(tài),結(jié)合waitGroup,如果在主函數(shù)等待使用通道的函數(shù)執(zhí)行結(jié)束,而使用通道的函數(shù)并且通道陷入阻塞狀態(tài),如果有其他函數(shù)對(duì)其進(jìn)行喚醒則不會(huì)死鎖,如果沒(méi)有其他函數(shù)可以對(duì)其進(jìn)行喚醒則會(huì)拋出死鎖異常。
總結(jié):
通道將數(shù)據(jù)隔離在每一份通道內(nèi),在并發(fā)的情況下可以很好的使用數(shù)據(jù),當(dāng)然要熟悉通道阻塞的幾種情況,避免死鎖異常。
到此這篇關(guān)于Go語(yǔ)言中的通道channel詳情的文章就介紹到這了,更多相關(guān)Go語(yǔ)言中的通道channel內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go語(yǔ)言常見(jiàn)錯(cuò)誤接口污染解決分析
這篇文章主要為大家介紹了Go語(yǔ)言常見(jiàn)錯(cuò)誤接口污染解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01
使用Go實(shí)現(xiàn)健壯的內(nèi)存型緩存的方法
這篇文章主要介紹了使用Go實(shí)現(xiàn)健壯的內(nèi)存型緩存,本文比較了字節(jié)緩存和結(jié)構(gòu)體緩存的優(yōu)劣勢(shì),介紹了緩存穿透、緩存錯(cuò)誤、緩存預(yù)熱、緩存?zhèn)鬏?、故障轉(zhuǎn)移、緩存淘汰等問(wèn)題,并對(duì)一些常見(jiàn)的緩存庫(kù)進(jìn)行了基準(zhǔn)測(cè)試,需要的朋友可以參考下2022-05-05
go語(yǔ)言實(shí)現(xiàn)將重要數(shù)據(jù)寫(xiě)入圖片中
本文給大家分享的是go語(yǔ)言實(shí)現(xiàn)將數(shù)據(jù)的二進(jìn)制形式寫(xiě)入圖像紅色通道數(shù)據(jù)二進(jìn)制的低位,從而實(shí)現(xiàn)將重要數(shù)據(jù)隱藏,有需要的小伙伴參考下吧。2015-03-03
模塊一 GO語(yǔ)言基礎(chǔ)知識(shí)-庫(kù)源碼文件
這篇文章主要介紹了模塊一 GO語(yǔ)言基礎(chǔ)知識(shí)-庫(kù)源碼文件,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-01-01
gin正確多次讀取http?request?body內(nèi)容實(shí)現(xiàn)詳解
這篇文章主要為大家介紹了gin正確多次讀取http?request?body內(nèi)容實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01

