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循環