Golang channel

channel簡介

channel俗稱管道埋合,用于數(shù)據(jù)傳遞或數(shù)據(jù)共享备徐,其本質(zhì)是一個先進先出的隊列,使用goroutine+channel進行數(shù)據(jù)通訊簡單高效甚颂,同時也線程安全蜜猾,多個goroutine可同時修改一個channel,不需要加鎖 振诬。

channel可分為三種類型:

  • 只讀channel:只能讀channel里面數(shù)據(jù)蹭睡,不可寫入

  • 只寫channel:只能寫數(shù)據(jù),不可讀

  • 一般channel:可讀可寫

channel使用

定義和聲明

var readOnlyChan <-chan int            // 只讀chan
var writeOnlyChan chan<- int           // 只寫chan
var mychan  chan int                     //讀寫channel
//定義完成以后需要make來分配內(nèi)存空間赶么,不然使用會deadlock
mychannel = make(chan int,10)

//或者
read_only := make (<-chan int,10)//定義只讀的channel
write_only := make (chan<- int,10)//定義只寫的channel
read_write := make (chan int,10)//可同時讀寫

//操作
write_only <- "wd"  //寫數(shù)據(jù)
a := <- read_only //讀取數(shù)據(jù)
a, ok := <- read_only  //優(yōu)雅的讀取數(shù)據(jù)

注:

  • 讀寫操作注意:
    • 管道如果未關(guān)閉肩豁,在讀取超時會則會引發(fā)deadlock異常
    • 管道如果關(guān)閉進行寫入數(shù)據(jù)會pannic
    • 當管道中沒有數(shù)據(jù)時候再行讀取或讀取到默認值,如int類型默認值是0
  • 循環(huán)管道注意:
    • 使用range循環(huán)管道辫呻,如果管道未關(guān)閉會引發(fā)deadlock錯誤清钥。
    • 如果采用for死循環(huán)已經(jīng)關(guān)閉的管道,當管道沒有數(shù)據(jù)時候放闺,讀取的數(shù)據(jù)會是管道的默認值祟昭,并且循環(huán)不會退出。

示例代碼:

package main

import (
    "fmt"
    "time"
)

func main() {
    mychannel := make(chan int,10)
    for i := 0;i < 10;i++{
        mychannel <- i
    }
    close(mychannel)  //關(guān)閉管道
    fmt.Println("data lenght: ",len(mychannel))
    for  v := range mychannel {  //循環(huán)管道
        fmt.Println(v)
    }
    fmt.Printf("data lenght:  %d",len(mychannel))
}

帶緩沖區(qū)channel和不帶緩沖區(qū)channel

帶緩沖區(qū)channel:定義聲明時候制定了緩沖區(qū)大小(長度)雄人,可以保存多個數(shù)據(jù)从橘。

ch := make(chan int ,10) //帶緩沖區(qū)

不帶緩沖區(qū)channel:只能存一個數(shù)據(jù),并且只有當該數(shù)據(jù)被取出時候才能存下一個數(shù)據(jù)础钠。

ch := make(chan int) //不帶緩沖區(qū)

channel實現(xiàn)作業(yè)池

創(chuàng)建三個channel,一個channel用于接受任務叉谜,一個channel用于保持結(jié)果旗吁,還有個channel用于決定程序退出的時候。

package main

import (
    "fmt"
)

func Task(taskch, resch chan int, exitch chan bool) {
    defer func() {   //異常處理
        err := recover()
        if err != nil {
            fmt.Println("do task error:", err)
            return
        }
    }()

    for t := range taskch { //  處理任務
        fmt.Println("do task :", t)
        resch <- t //
    }
    exitch <- true //處理完發(fā)送退出信號
}

func main() {
    taskch := make(chan int, 20) //任務管道
    resch := make(chan int, 20)  //結(jié)果管道
    exitch := make(chan bool, 5) //退出管道
    go func() {
        for i := 0; i < 10; i++ {
            taskch <- i
        }
        close(taskch)
    }()

    for i := 0; i < 5; i++ {  //啟動5個goroutine做任務
        go Task(taskch, resch, exitch)
    }

    go func() { //等5個goroutine結(jié)束
        for i := 0; i < 5; i++ {
            <-exitch
        }
        close(resch)  //任務處理完成關(guān)閉結(jié)果管道停局,不然range報錯
        close(exitch)  //關(guān)閉退出管道
    }()

    for res := range resch{  //打印結(jié)果
        fmt.Println("task res:",res)
    }
}

select-case實現(xiàn)非阻塞channel

原理通過select+case加入一組管道很钓,當滿足(這里說的滿足意思是有數(shù)據(jù)可讀或者可寫)select中的某個case時候,那么該case返回董栽,若都不滿足case码倦,則走default分支。

package main

import (
    "fmt"
)

func send(c chan int)  {
    for i :=1 ; i<10 ;i++  {
    c <-i
    fmt.Println("send data : ",i)
    }
}

func main() {
    resch := make(chan int,20)
    strch := make(chan string,10)
    go send(resch)
    strch <- "wd"
    select {
    case a := <-resch:
        fmt.Println("get data : ", a)
    case b := <-strch:
        fmt.Println("get data : ", b)
    default:
        fmt.Println("no channel actvie")

    }
}

channel頻率控制

在對channel進行讀寫的時锭碳,go還提供了非常人性化的操作袁稽,那就是對讀寫的頻率控制,通過time.Ticke實現(xiàn)

package main

import (
    "time"
    "fmt"
)

func main(){
    requests:= make(chan int ,5)
    for i:=1;i<5;i++{
        requests<-i
    }
    close(requests)
    limiter := time.Tick(time.Second*1)
    for req:=range requests{
        <-limiter
        fmt.Println("requets",req,time.Now()) //執(zhí)行到這里擒抛,需要隔1秒才繼續(xù)往下執(zhí)行推汽,time.Tick(timer)上面已定義
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末补疑,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子歹撒,更是在濱河造成了極大的恐慌莲组,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件暖夭,死亡現(xiàn)場離奇詭異锹杈,居然都是意外死亡,警方通過查閱死者的電腦和手機迈着,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進店門竭望,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人寥假,你說我怎么就攤上這事市框。” “怎么了糕韧?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵枫振,是天一觀的道長。 經(jīng)常有香客問我萤彩,道長粪滤,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任雀扶,我火速辦了婚禮杖小,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘愚墓。我一直安慰自己予权,他們只是感情好,可當我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布浪册。 她就那樣靜靜地躺著扫腺,像睡著了一般。 火紅的嫁衣襯著肌膚如雪村象。 梳的紋絲不亂的頭發(fā)上笆环,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機與錄音厚者,去河邊找鬼躁劣。 笑死,一個胖子當著我的面吹牛库菲,可吹牛的內(nèi)容都是我干的账忘。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼闪萄!你這毒婦竟也來了梧却?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤败去,失蹤者是張志新(化名)和其女友劉穎放航,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體圆裕,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡广鳍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了吓妆。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赊时。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖行拢,靈堂內(nèi)的尸體忽然破棺而出祖秒,到底是詐尸還是另有隱情,我是刑警寧澤舟奠,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布竭缝,位于F島的核電站,受9級特大地震影響沼瘫,放射性物質(zhì)發(fā)生泄漏抬纸。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一耿戚、第九天 我趴在偏房一處隱蔽的房頂上張望湿故。 院中可真熱鬧,春花似錦膜蛔、人聲如沸坛猪。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽砚哆。三九已至,卻和暖如春屑墨,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背纷铣。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工卵史, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人搜立。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓以躯,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子忧设,可洞房花燭夜當晚...
    茶點故事閱讀 44,927評論 2 355

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