golang的channel剖析

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

概述

  為了並發的goroutines之間的通訊,golang使用了管道channel。你可以通過一個goroutines向channel發送資料,然後從另一個goroutine接收它

通常我們會使用make來建立channel   -----   make(chan valType , [size])。

寫入 channel    c<-

讀取channel    <-c

分類


一   無緩衝

make建立時忽略第二個參數即可建立無緩衝channel執行個體如下:

// csdnTest.gopackage mainimport ("fmt"        "time")func main() {messages := make(chan string)go func() {messages <- "hello"}()msg := <-messages      fmt.Println(msg)}

值得注意的是:無緩衝channel只有接收和發送方都準備好了,channel才能正常工作,上述代碼中如果我們把msg := <-messages這句注釋掉,那麼messages <- "hello"將會一直阻塞。

在這裡做個猜想: 無緩衝的buffer只是直使用了ipc的pipe,pipe兩端都開啟時才能使用。“<-”被解釋為開啟寫端,“->被解釋為開啟讀端”


二  有緩衝

樣本:

// csdnTest.gopackage mainimport ("fmt")func main() {messages := make(chan string, 2)messages <- "hello"messages <- "world"fmt.Println(<-msg)fmt.Println(<-msg)}

說明:當建立有緩衝的buffer時,就不需要有準備好的接收器來接受資料,資料可以存在channel的緩衝區中,有緩衝的channel有如下特性:

1:資料未滿可以寫,當資料滿了再寫阻塞。

2:資料未空可以讀,當資料空了再讀阻塞。

通過上面的特性可以做個大膽的猜測,有緩衝的是通過msg-queue來實現的。

有緩衝和無緩衝從底層的實現就不同,因為他們使用了不同的ipc。


三  非阻塞

正常情況下的channel讀和寫都是阻塞的,然而我們可以使用一個帶有default的select來觸發非阻塞的channle。原本select也是阻塞的,在加入default時select本身也變為非阻塞

舉個例子:

// csdnTest.gopackage mainimport "fmt"func main() {messages := make(chan string)signals := make(chan bool)//message和signals是無緩衝channel,因為接收器和發送器沒同時準備好,所以channel無法使用。//下面所有select會輸出default的內容select {case msg := <-messages:fmt.Println("received message", msg)default:fmt.Println("no message received")}msg := "hi"select {case messages <- msg:fmt.Println("sent message", msg)default:fmt.Println("no message sent")}select {case msg := <-messages:fmt.Println("received message", msg)case sig := <-signals:fmt.Println("received signal", sig)default:fmt.Println("no activity")}}

有興趣同學將上面無緩衝的改成有緩衝的嘗試一下。

至於select為何在加入default後channel和自身都未非阻塞了,你可以去看看go源碼select.go這個源檔案,-------------------也可以閱讀我的下一期部落格。


四   channel的用例


4.1 處理逾時

    c := make(chan string, 1)    go func() {        time.Sleep(time.Second * 3)        c <- "inner goroutine"    }()    select {    case res := <-c:        fmt.Println(res)    case <-time.After(time.Second * 1):        fmt.Println("timeout")    }


4.2 channel關閉

      關閉一個channel時,就不能向該channel中寫資料了。通常我們用一個值傳回值來接收channel的資料,但此時可以用兩個傳回值  (valeu,b:=<-c)   來捕獲channel是否關閉   b取值false或true。

當我們處理一個需要結束的任務,可採用下面的方式來調度

jobs := make(chan int, 10)done := make(chan bool)go func() {for {j, more := <-jobsif more {fmt.Println("received job", j)} else {fmt.Println("received all jobs")done <- truereturn}}}()for j := 1; j <= 3; j++ {jobs <- jfmt.Println("sent job", j)}close(jobs)

   

4.3  資料乒乓球式的流轉


舉一個golang官網比較知名的一個例子:

package mainimport "fmt"func ping(pings chan<- string, msg string) {    pings <- msg}func pong(pings <-chan string, pongs chan<- string) {    msg := <-pings    pongs <- msg}func main() {    pings := make(chan string, 1)    pongs := make(chan string, 1)    ping(pings, "passed message")    pong(pings, pongs)    fmt.Println(<-pongs)}











謝謝各位的閱讀


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.