GO Channel

1 不緩存的channel數據庫

以最簡單方式調用make函數建立的時一個無緩存的channel,可是咱們也能夠指定第二個整形參數,對應channel的容量。若是channel的容量大於零,那麼該channel就是帶緩存的channel緩存

ch = make(chan int) // unbuffered channel ch = make(chan int, 0) // unbuffered channel

一個基於無緩存Channels的發送操做將致使發送者goroutine阻塞,直到另外一個goroutine在相同的Channels上執行接收操做,當發送的值經過Channels成功傳輸以後,兩個goroutine能夠繼續執行後面的語句。
反之,若是接收操做先發生,那麼接收者goroutine也將阻塞,
直到有另外一個goroutine在相同的Channels上執行發送操做

func gosum(s []int, c chan int) {
    sum := 0
 
    for _, v := range s {
        sum += v
    }
    c <- sum // send sum to c
}

    var si []int = []int{1, 2, 3, 4}
    chan_c := make(chan int, 0)
 
    go gosum(si, chan_c)
 
    rs := <-chan_c
 
    fmt.Println(rs)
 

2 緩存的channeldom

帶緩存的Channel內部持有一個元素隊列。經過緩存的使用,能夠儘可能避免阻塞,提供應用的性能。隊列的最大容量是在調用make函數建立channel時經過第二個參數指定的,好比函數

ch = make(chan int, 3) // buffered channel with capacity 3
咱們能夠在無阻塞的狀況下連續向新建立的channel發送三個值
此刻,channel的內部緩存隊列將是滿的,若是有第四個發送操做將發生阻塞。channel的緩存隊列解耦了接收和發送的goroutinech <- "A" ch <- "B" ch <- "C"

3 channel & Range性能

    c := make(chan int)
    go func() {
        for i := 0; i < 10; i = i + 1 {
            c <- i
            time.Sleep(1 * time.Second)
        }
        close(c)
    }()
 
    for i := range c {
        fmt.Println(i)
    }
 
    time.Sleep(100 * time.Second)

 產生的迭代值爲Channel中發送的值,它會一直迭代知道channel被關閉。上面的例子中若是把  註釋掉,程序會一直阻塞在  那一行range cclose(c)for …… range
 

4 單向channelui

Go語言的類型系統提供了單方向的channel類型,分別用於只發送或只接收的channel。類型chan<- int表示一個只發送int的channel,只能發送不能接收。相反,類型<-chan int表示一個只接收int的channel,只能接收不能發送。(箭頭<-和關鍵字chan的相對位置代表了channel的方向。)這種限制將在編譯期檢測。spa

由於關閉操做只用於斷言再也不向channel發送新的數據,因此只有在發送者所在的goroutine纔會調用close函數,所以對一個只接收的channel調用close將是一個編譯錯誤code

func gosum(s []int, c chan<- int) {
    sum := 0
 
    for _, v := range s {
        sum += v
    }
    c <- sum // send sum to c
}

5 channel&goroutines應用-批量查詢數據庫隊列

func Query(conns []Conn, query string) Result {
    ch := make(chan Result, len(conns))  // buffered
    for _, conn := range conns {
        go func(c Conn) {
            ch <- c.DoQuery(query):
        }(conn)
    }
    return <-ch
}
 

6 selectci

select 語句選擇一組可能的send操做和receive操做去處理。它相似 switch ,可是隻是用來處理通信(communication)操做。它的 case 能夠是send語句,也能夠是receive語句,亦或者 default 。receive 語句能夠將值賦值給一個或者兩個變量。它必須是一個receive操做。最多容許有一個 default case ,它能夠放在case列表的任何位置,儘管咱們大部分會將它放在最後。

若是有同時多個case去處理,好比同時有多個channel能夠接收數據,那麼Go會僞隨機的選擇一個case處理(pseudo-random)。若是沒有case須要處理,則會選擇 default 去處理,若是 default case 存在的狀況下。若是沒有 default case ,則 select 語句會阻塞,直到某個case須要處理

select 語句和 switch 語句同樣,它不是循環,它只會選擇一個case來處理,若是想一直處理channel,你能夠在外面加一個無限的for循環

相關文章
相關標籤/搜索