1.基本知識
通道類型的值本身就是併發安全的,go語言自帶的唯一一個可以滿足併發安全的類型。通道相當於一個先進先出的隊列,發送和接收使用操作符 <-
2.初始化
make(chan type,int)
type: int, string....
int: 可選。通道的容量。0表示不帶緩衝的通道,1表示帶緩衝的通道。
1.初始化容量爲3的雙向通道
package main
import "fmt"
func main() {
ch1 := make(chan int, 3)
ch1 <- 2
ch1 <- 1
ch1 <- 3
elem1 := <-ch1
fmt.Printf("The first element received from channel ch1: %v\n",
elem1)
}
2.初始化只讀管道
ch1:=make(chan<- int, 1)
example:
func getIntChan() <-chan int {
num := 5
ch := make(chan int, num)
for i := 0; i < num; i++ {
ch <- i
}
close(ch)
return ch
}
3.初始化只寫管道
ch1:=make(<-chan int, 1)
example:
func SendInt(ch chan<- int) {
ch <- rand.Intn(1000)
}
3.注意
a.對同一個通道來說,同一時間發送和接收拾互斥的。
b.元素進入通道是複製的副本。
c.緩衝通道滿了以後會阻塞通道。非緩衝通道一開始就會被阻塞,直到有配對的接收操作,纔開始傳輸數據,將數據直接複製到緩衝通道,在複製給接收方。
d.如果通道爲nil,直接發生永久堵塞。
e.確保由發送方關閉通道。如果接收方關閉通道,再次向發送方發送會引發panic。
4.遍歷chan
這種方法有一定的侷限性,如果intChan2 沒有元素或者爲nil,那麼就會在這一行阻塞。
func getIntChan() <-chan int {
num := 5
ch := make(chan int, num)
for i := 0; i < num; i++ {
ch <- i
}
close(ch)
return ch
}
intChan2 := getIntChan()
for elem := range intChan2 {
fmt.Printf("The element in intChan2: %v\n", elem)
}
5.select語句
chan專用。類似於 switch,不過select中首先會對所有case求值,然後纔開始選擇,並不是順序求值選擇。如果case 語句阻塞,也代表求值失敗,知道有條件滿足爲止。如果有多個case條件滿足,則用僞隨機算法隨機選擇一個分支執行。若所有分支都未被選中,則默認分支執行。
example1:
// 準備好幾個通道。
intChannels := [3]chan int{
make(chan int, 1),
make(chan int, 1),
make(chan int, 1),
}
// 隨機選擇一個通道,並向它發送元素值。
index := rand.Intn(3)
fmt.Printf("The index: %d\n", index)
intChannels[index] <- index
// 哪一個通道中有可取的元素值,哪個對應的分支就會被執行。
select {
case <-intChannels[0]:
fmt.Println("The first candidate case is selected.")
case <-intChannels[1]:
fmt.Println("The second candidate case is selected.")
case elem := <-intChannels[2]:
fmt.Printf("The third candidate case is selected, the element is %d.\n", elem)
default:
fmt.Println("No candidate case is selected!")
}
example2:
intChan := make(chan int, 1)
// 一秒後關閉通道。
time.AfterFunc(time.Second, func() {
close(intChan)
})
select {
case _, ok := <-intChan:
if !ok {
fmt.Println("The candidate case is closed.")
break
}
fmt.Println("The candidate case is selected.")
}