日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 人文社科 > 生活经验 >内容正文

生活经验

管道通信C语言,Go语言通道(chan)——goroutine之间通信的管道

發(fā)布時(shí)間:2023/11/27 生活经验 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 管道通信C语言,Go语言通道(chan)——goroutine之间通信的管道 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

如果說(shuō) goroutine 是 Go語(yǔ)言程序的并發(fā)體的話(huà),那么 channels 就是它們之間的通信機(jī)制。一個(gè) channels 是一個(gè)通信機(jī)制,它可以讓一個(gè) goroutine 通過(guò)它給另一個(gè) goroutine 發(fā)送值信息。每個(gè) channel 都有一個(gè)特殊的類(lèi)型,也就是 channels 可發(fā)送數(shù)據(jù)的類(lèi)型。一個(gè)可以發(fā)送 int 類(lèi)型數(shù)據(jù)的 channel 一般寫(xiě)為 chan int。

Go語(yǔ)言提倡使用通信的方法代替共享內(nèi)存,當(dāng)一個(gè)資源需要在 goroutine 之間共享時(shí),通道在 goroutine 之間架起了一個(gè)管道,并提供了確保同步交換數(shù)據(jù)的機(jī)制。聲明通道時(shí),需要指定將要被共享的數(shù)據(jù)的類(lèi)型。可以通過(guò)通道共享內(nèi)置類(lèi)型、命名類(lèi)型、結(jié)構(gòu)類(lèi)型和引用類(lèi)型的值或者指針。

這里通信的方法就是使用通道(channel),如下圖所示。

圖:goroutine 與 channel 的通信

在地鐵站、食堂、洗手間等公共場(chǎng)所人很多的情況下,大家養(yǎng)成了排隊(duì)的習(xí)慣,目的也是避免擁擠、插隊(duì)導(dǎo)致的低效的資源使用和交換過(guò)程。代碼與數(shù)據(jù)也是如此,多個(gè) goroutine 為了爭(zhēng)搶數(shù)據(jù),勢(shì)必造成執(zhí)行的低效率,使用隊(duì)列的方式是最高效的,channel 就是一種隊(duì)列一樣的結(jié)構(gòu)。

通道的特性

Go語(yǔ)言中的通道(channel)是一種特殊的類(lèi)型。在任何時(shí)候,同時(shí)只能有一個(gè) goroutine 訪問(wèn)通道進(jìn)行發(fā)送和獲取數(shù)據(jù)。goroutine 間通過(guò)通道就可以通信。

通道像一個(gè)傳送帶或者隊(duì)列,總是遵循先入先出(First In First Out)的規(guī)則,保證收發(fā)數(shù)據(jù)的順序。

聲明通道類(lèi)型

通道本身需要一個(gè)類(lèi)型進(jìn)行修飾,就像切片類(lèi)型需要標(biāo)識(shí)元素類(lèi)型。通道的元素類(lèi)型就是在其內(nèi)部傳輸?shù)臄?shù)據(jù)類(lèi)型,聲明如下:

var 通道變量 chan 通道類(lèi)型

通道類(lèi)型:通道內(nèi)的數(shù)據(jù)類(lèi)型。

通道變量:保存通道的變量。

chan 類(lèi)型的空值是 nil,聲明后需要配合 make 后才能使用。

創(chuàng)建通道

通道是引用類(lèi)型,需要使用 make 進(jìn)行創(chuàng)建,格式如下:

通道實(shí)例 := make(chan 數(shù)據(jù)類(lèi)型)

數(shù)據(jù)類(lèi)型:通道內(nèi)傳輸?shù)脑仡?lèi)型。

通道實(shí)例:通過(guò)make創(chuàng)建的通道句柄。

請(qǐng)看下面的例子:

ch1 := make(chan int) // 創(chuàng)建一個(gè)整型類(lèi)型的通道

ch2 := make(chan interface{}) // 創(chuàng)建一個(gè)空接口類(lèi)型的通道, 可以存放任意格式

type Equip struct{ /* 一些字段 */ }

ch2 := make(chan *Equip) // 創(chuàng)建Equip指針類(lèi)型的通道, 可以存放*Equip

使用通道發(fā)送數(shù)據(jù)

通道創(chuàng)建后,就可以使用通道進(jìn)行發(fā)送和接收操作。

1) 通道發(fā)送數(shù)據(jù)的格式

通道的發(fā)送使用特殊的操作符

通道變量

通道變量:通過(guò)make創(chuàng)建好的通道實(shí)例。

值:可以是變量、常量、表達(dá)式或者函數(shù)返回值等。值的類(lèi)型必須與ch通道的元素類(lèi)型一致。

2) 通過(guò)通道發(fā)送數(shù)據(jù)的例子

使用 make 創(chuàng)建一個(gè)通道后,就可以使用

// 創(chuàng)建一個(gè)空接口通道

ch := make(chan interface{})

// 將0放入通道中

ch

// 將hello字符串放入通道中

ch

3) 發(fā)送將持續(xù)阻塞直到數(shù)據(jù)被接收

把數(shù)據(jù)往通道中發(fā)送時(shí),如果接收方一直都沒(méi)有接收,那么發(fā)送操作將持續(xù)阻塞。Go 程序運(yùn)行時(shí)能智能地發(fā)現(xiàn)一些永遠(yuǎn)無(wú)法發(fā)送成功的語(yǔ)句并做出提示,代碼如下:

package main

func main() {

// 創(chuàng)建一個(gè)整型通道

ch := make(chan int)

// 嘗試將0通過(guò)通道發(fā)送

ch

}

運(yùn)行代碼,報(bào)錯(cuò):

fatal error: all goroutines are asleep - deadlock!

報(bào)錯(cuò)的意思是:運(yùn)行時(shí)發(fā)現(xiàn)所有的 goroutine(包括main)都處于等待 goroutine。也就是說(shuō)所有 goroutine 中的 channel 并沒(méi)有形成發(fā)送和接收對(duì)應(yīng)的代碼。

使用通道接收數(shù)據(jù)

通道接收同樣使用

① 通道的收發(fā)操作在不同的兩個(gè) goroutine 間進(jìn)行。

由于通道的數(shù)據(jù)在沒(méi)有接收方處理時(shí),數(shù)據(jù)發(fā)送方會(huì)持續(xù)阻塞,因此通道的接收必定在另外一個(gè) goroutine 中進(jìn)行。

② 接收將持續(xù)阻塞直到發(fā)送方發(fā)送數(shù)據(jù)。

如果接收方接收時(shí),通道中沒(méi)有發(fā)送方發(fā)送數(shù)據(jù),接收方也會(huì)發(fā)生阻塞,直到發(fā)送方發(fā)送數(shù)據(jù)為止。

③ 每次接收一個(gè)元素。

通道一次只能接收一個(gè)數(shù)據(jù)元素。

通道的數(shù)據(jù)接收一共有以下 4 種寫(xiě)法。

1) 阻塞接收數(shù)據(jù)

阻塞模式接收數(shù)據(jù)時(shí),將接收變量作為

data :=

執(zhí)行該語(yǔ)句時(shí)將會(huì)阻塞,直到接收到數(shù)據(jù)并賦值給 data 變量。

2) 非阻塞接收數(shù)據(jù)

使用非阻塞方式從通道接收數(shù)據(jù)時(shí),語(yǔ)句不會(huì)發(fā)生阻塞,格式如下:

data, ok :=

data:表示接收到的數(shù)據(jù)。未接收到數(shù)據(jù)時(shí),data 為通道類(lèi)型的零值。

ok:表示是否接收到數(shù)據(jù)。

非阻塞的通道接收方法可能造成高的 CPU 占用,因此使用非常少。如果需要實(shí)現(xiàn)接收超時(shí)檢測(cè),可以配合 select 和計(jì)時(shí)器 channel 進(jìn)行,可以參見(jiàn)后面的內(nèi)容。

3) 接收任意數(shù)據(jù),忽略接收的數(shù)據(jù)

阻塞接收數(shù)據(jù)后,忽略從通道返回的數(shù)據(jù),格式如下:

執(zhí)行該語(yǔ)句時(shí)將會(huì)發(fā)生阻塞,直到接收到數(shù)據(jù),但接收到的數(shù)據(jù)會(huì)被忽略。這個(gè)方式實(shí)際上只是通過(guò)通道在 goroutine 間阻塞收發(fā)實(shí)現(xiàn)并發(fā)同步。

使用通道做并發(fā)同步的寫(xiě)法,可以參考下面的例子:

package main

import (

"fmt"

)

func main() {

// 構(gòu)建一個(gè)通道

ch := make(chan int)

// 開(kāi)啟一個(gè)并發(fā)匿名函數(shù)

go func() {

fmt.Println("start goroutine")

// 通過(guò)通道通知main的goroutine

ch

fmt.Println("exit goroutine")

}()

fmt.Println("wait goroutine")

// 等待匿名goroutine

fmt.Println("all done")

}

執(zhí)行代碼,輸出如下:

wait goroutine

start goroutine

exit goroutine

all done

代碼說(shuō)明如下:

第 10 行,構(gòu)建一個(gè)同步用的通道。

第 13 行,開(kāi)啟一個(gè)匿名函數(shù)的并發(fā)。

第 18 行,匿名 goroutine 即將結(jié)束時(shí),通過(guò)通道通知 main 的 goroutine,這一句會(huì)一直阻塞直到 main 的 goroutine 接收為止。

第 27 行,開(kāi)啟 goroutine 后,馬上通過(guò)通道等待匿名 goroutine 結(jié)束。

4) 循環(huán)接收

通道的數(shù)據(jù)接收可以借用 for range 語(yǔ)句進(jìn)行多個(gè)元素的接收操作,格式如下:

for data := range ch {

}

通道 ch 是可以進(jìn)行遍歷的,遍歷的結(jié)果就是接收到的數(shù)據(jù)。數(shù)據(jù)類(lèi)型就是通道的數(shù)據(jù)類(lèi)型。通過(guò) for 遍歷獲得的變量只有一個(gè),即上面例子中的 data。

遍歷通道數(shù)據(jù)的例子請(qǐng)參考下面的代碼。

使用 for 從通道中接收數(shù)據(jù):

package main

import (

"fmt"

"time"

)

func main() {

// 構(gòu)建一個(gè)通道

ch := make(chan int)

// 開(kāi)啟一個(gè)并發(fā)匿名函數(shù)

go func() {

// 從3循環(huán)到0

for i := 3; i >= 0; i-- {

// 發(fā)送3到0之間的數(shù)值

ch

// 每次發(fā)送完時(shí)等待

time.Sleep(time.Second)

}

}()

// 遍歷接收通道數(shù)據(jù)

for data := range ch {

// 打印通道數(shù)據(jù)

fmt.Println(data)

// 當(dāng)遇到數(shù)據(jù)0時(shí), 退出接收循環(huán)

if data == 0 {

break

}

}

}

執(zhí)行代碼,輸出如下:

3

2

1

0

代碼說(shuō)明如下:

第 12 行,通過(guò) make 生成一個(gè)整型元素的通道。

第 15 行,將匿名函數(shù)并發(fā)執(zhí)行。

第 18 行,用循環(huán)生成 3 到 0 之間的數(shù)值。

第 21 行,將 3 到 0 之間的數(shù)值依次發(fā)送到通道 ch 中。

第 24 行,每次發(fā)送后暫停 1 秒。

第 30 行,使用 for 從通道中接收數(shù)據(jù)。

第 33 行,將接收到的數(shù)據(jù)打印出來(lái)。

第 36 行,當(dāng)接收到數(shù)值 0 時(shí),停止接收。如果繼續(xù)發(fā)送,由于接收 goroutine 已經(jīng)退出,沒(méi)有 goroutine 發(fā)送到通道,因此運(yùn)行時(shí)將會(huì)觸發(fā)宕機(jī)報(bào)錯(cuò)。

總結(jié)

以上是生活随笔為你收集整理的管道通信C语言,Go语言通道(chan)——goroutine之间通信的管道的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。