Go基礎(chǔ)——channel通道

CSP

要想理解 channel 要先知道 CSP 模型郊愧。CSP 是 Communicating Sequential Process 的簡稱娜搂,中文可以叫做通信順序進(jìn)程漠秋,是一種并發(fā)編程模型吻谋,由 Tony Hoare 于 1977 年提出辽幌。簡單來說增淹,CSP 模型由并發(fā)執(zhí)行的實體(線程或者進(jìn)程)所組成,實體之間通過發(fā)送消息進(jìn)行通信乌企,這里發(fā)送消息時使用的就是通道,或者叫 channel成玫。CSP 模型的關(guān)鍵是關(guān)注 channel加酵,而不關(guān)注發(fā)送消息的實體。Go 語言實現(xiàn)了 CSP 部分理論哭当,goroutine 對應(yīng) CSP 中并發(fā)執(zhí)行的實體猪腕,channel 也就對應(yīng)著 CSP 中的 channel。

channel

channel是Go語言在語言級別提供的goroutine間的通信方式钦勘。我們可以使用channel在兩個或多個goroutine之間傳遞消息陋葡。在聲明一個通道變量的時候,必須確定通道類型的傳遞的元素類型彻采,通過channel傳遞對象的過程和調(diào)用函數(shù)時的參數(shù)傳遞類型必須一致腐缤。
channel的聲明形式為:

 var 變量名稱 chan 通道元素類型  

與一般的變量聲明不同的地方僅僅是在類型之前加了chan關(guān)鍵字,初始化一個channel也很簡單,直接使用內(nèi)置的函數(shù)make()即可:

    make(chan Type) //等價于make(chan Type, 0)
    make(chan Type, capacity)

make函數(shù)可接受兩個參數(shù)肛响。第一個參數(shù)是代表了將被初始化的值的類型的字面量(比如chan int)岭粤,而第二個參數(shù)則是通道的容量,是可選參數(shù)特笋,例如剃浇,若我們想要初始化一個長度為3且元素類型為int的通道值,則需要這樣寫:

make(chan int, 3)   

確切地說猎物,通道值的長度應(yīng)該被稱為其緩存的尺寸虎囚。換句話說,它代表著通道值中可以暫存的數(shù)據(jù)的個數(shù)蔫磨。因此通道容量不能是負(fù)數(shù)淘讥,一個通道類似于一個先進(jìn)先出(FIFO)的隊列,即:越早被放入(或稱發(fā)送)到通道值的數(shù)據(jù)會越先被取出(或稱接收)在channel的用法中质帅。

chan數(shù)據(jù)發(fā)送與接收

chan數(shù)據(jù)發(fā)送與接收都是用到左尖括號與減號組合(<-),一個左尖括號緊接著一個減號的組合形似一個箭頭适揉,箭頭的方向代表了元素值的傳輸方向留攒。
** 發(fā)送數(shù)據(jù)<-**
向channel發(fā)送(寫入)數(shù)據(jù)通常會導(dǎo)致程序阻塞,直到有其他goroutine從這個channel中讀取數(shù)據(jù)嫉嘀。下面的程序會出現(xiàn)死鎖:

func foo(in chan int) {
    fmt.Println(<-in)
}

func main() {
    out := make(chan int)
    out <- 1
    go foo(out)
}

讀取數(shù)據(jù)

value := <- ch  
value, ok := <-ch    //功能同上炼邀,同時檢查通道是否已關(guān)閉或者是否為空

因此需要特別注意的是:channel接收和發(fā)送數(shù)據(jù)都是阻塞的,當(dāng)把數(shù)據(jù)發(fā)送到信道時剪侮,程序控制會在發(fā)送數(shù)據(jù)的語句處發(fā)生阻塞拭宁,直到有其它 Go 協(xié)程從信道讀取到數(shù)據(jù),才會解除阻塞瓣俯。與此類似杰标,當(dāng)讀取信道的數(shù)據(jù)時,如果沒有其它的協(xié)程把數(shù)據(jù)寫入到這個信道彩匕,那么讀取過程就會一直阻塞著腔剂。

import "fmt"

func main() {
    c := make(chan int)
    go func(){
        defer fmt.Println("子協(xié)程結(jié)束")
        fmt.Println("子協(xié)程正在運行")
        c<-6
    }()
    num := <-c
    fmt.Println(num)
    fmt.Println("main協(xié)程結(jié)束")
}

for range 遍歷信道

for range 循環(huán)用于在一個信道關(guān)閉之前,從信道接收數(shù)據(jù)驼仪。

func producer(chnl chan int) {
    for i := 0; i < 10; i++ {
        chnl <- i
    }
    close(chnl)
}
func main() {
    ch := make(chan int)
    go producer(ch)
    for {
        v, ok := <-ch
        if ok == false {
            break
        }
        fmt.Println("Received ", v, ok)
    }
}

阻塞性質(zhì)

Channel 的讀取和寫入操作在各自的協(xié)程內(nèi)部都是阻塞的掸犬。意思就是,如果管道滿了绪爸,一個對channel放入數(shù)據(jù)的操作就會阻塞湾碎,直到有某個routine從channel中取出數(shù)據(jù),這個放入數(shù)據(jù)的操作才會執(zhí)行奠货。相反同理介褥,如果管道是空的,一個從channel取出數(shù)據(jù)的操作就會阻塞递惋,直到某個routine向這個channel中放入數(shù)據(jù)柔滔,這個取出數(shù)據(jù)的操作才會執(zhí)行。

func main() {
    ch := make(chan int, 3)
    ch <- 1
    fmt.Println("發(fā)送數(shù)據(jù)1")
    ch <- 2
    fmt.Println("發(fā)送數(shù)據(jù)2")
    ch <- 3
    fmt.Println("發(fā)送數(shù)據(jù)3")
    ch <- 4 //這一行操作就會發(fā)生阻塞丹墨,因為前三行的放入數(shù)據(jù)的操作已經(jīng)把channel填滿了
    fmt.Println("發(fā)送數(shù)據(jù)4")
}

主routine要向channel中放入一個數(shù)據(jù)廊遍,但是因為channel沒有緩沖,相當(dāng)于channel一直都是滿的贩挣,所以這里會發(fā)生阻塞,主routine在這里一阻塞喉前,造成死鎖!

func main() {
    ch := make(chan int)
    <-ch //這一行會發(fā)生阻塞王财,因為channel才剛創(chuàng)建卵迂,是空的,沒有東西可以取出
}

從這里可以看出绒净,對于無緩沖的channel见咒,放入操作和取出操作不能再同一個routine中,而且應(yīng)該是先確保有某個routine對它執(zhí)行取出操作挂疆,然后才能在另一個routine中執(zhí)行放入操作改览。

select

超時控制

time.After方法下翎,它返回一個類型為<-chan Time的單向的channel,在指定的時間發(fā)送一個當(dāng)前時間給返回的channel中宝当。

package main

import (
    "fmt"
    "time"
)

func main() {
    c := make(chan int)
    go func() {
        time.Sleep(2 * time.Second)
        c <- 1
    }()
    select {
    case res := <-c:
        fmt.Println("result", res)
    case <-time.After(1 * time.Second):
        fmt.Println("Timeout")
    }
}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末视事,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子庆揩,更是在濱河造成了極大的恐慌俐东,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,723評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件订晌,死亡現(xiàn)場離奇詭異虏辫,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)锈拨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評論 2 382
  • 文/潘曉璐 我一進(jìn)店門砌庄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人推励,你說我怎么就攤上這事鹤耍。” “怎么了验辞?”我有些...
    開封第一講書人閱讀 152,998評論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長喊衫。 經(jīng)常有香客問我跌造,道長,這世上最難降的妖魔是什么族购? 我笑而不...
    開封第一講書人閱讀 55,323評論 1 279
  • 正文 為了忘掉前任壳贪,我火速辦了婚禮,結(jié)果婚禮上寝杖,老公的妹妹穿的比我還像新娘违施。我一直安慰自己,他們只是感情好瑟幕,可當(dāng)我...
    茶點故事閱讀 64,355評論 5 374
  • 文/花漫 我一把揭開白布磕蒲。 她就那樣靜靜地躺著,像睡著了一般只盹。 火紅的嫁衣襯著肌膚如雪辣往。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評論 1 285
  • 那天殖卑,我揣著相機(jī)與錄音站削,去河邊找鬼。 笑死孵稽,一個胖子當(dāng)著我的面吹牛许起,可吹牛的內(nèi)容都是我干的十偶。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼园细,長吁一口氣:“原來是場噩夢啊……” “哼惦积!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起珊肃,我...
    開封第一講書人閱讀 37,019評論 0 259
  • 序言:老撾萬榮一對情侶失蹤荣刑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后伦乔,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體厉亏,經(jīng)...
    沈念sama閱讀 43,519評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,971評論 2 325
  • 正文 我和宋清朗相戀三年烈和,在試婚紗的時候發(fā)現(xiàn)自己被綠了爱只。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,100評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡招刹,死狀恐怖恬试,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情疯暑,我是刑警寧澤训柴,帶...
    沈念sama閱讀 33,738評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站妇拯,受9級特大地震影響幻馁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜越锈,卻給世界環(huán)境...
    茶點故事閱讀 39,293評論 3 307
  • 文/蒙蒙 一仗嗦、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧甘凭,春花似錦迎吵、人聲如沸规惰。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蹈矮,卻和暖如春砰逻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背泛鸟。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評論 1 262
  • 我被黑心中介騙來泰國打工蝠咆, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 45,547評論 2 354
  • 正文 我出身青樓刚操,卻偏偏與公主長得像闸翅,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子菊霜,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,834評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 有人把Go比作21世紀(jì)的C語言坚冀,第一是因為Go語言設(shè)計簡單,第二鉴逞,21世紀(jì)最重要的就是并行程序設(shè)計记某,而Go從語言層...
    夜空中乄最亮的星閱讀 1,854評論 0 3
  • channel[通道]是golang的一種重要特性,正是因為channel的存在才使得golang不同于其它語言构捡。...
    碼洞閱讀 2,216評論 0 51
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理液南,服務(wù)發(fā)現(xiàn),斷路器勾徽,智...
    卡卡羅2017閱讀 134,600評論 18 139
  • channel[通道]是golang的一種重要特性滑凉,正是因為channel的存在才使得golang不同于其它語言。...
    碼洞閱讀 22,423評論 1 53
  • 0303不能再想你(一) 相知 很久之后喘帚,我都還在想那個問題畅姊。就是情感專家說的那個問題,如果一個男人在半夜給你打電...
    一夏飄雪閱讀 437評論 7 3