### 上周的課程我們了解到了原子鎖和互斥鎖,都可以保證共享數據的讀寫,但是它們還是有點復雜,而且影響性能,對此,Go又為我們提供了一種工具,這就是通道,goroutine 運行的時候是相互獨立的。使用關鍵字 go 創建 goroutine 來運行函數。
### 一個死鎖的例子:
`
var ch1 chan int = make(chan int)
var ch2 chan int = make(chan int)
func say(s string) {
fmt.Println(s)
ch1 <- <- ch2 // ch1 等待 ch2流出的數據
}
func main() {
go say("hello")
<- ch1 // 堵塞主線
}
`
### 所以在多個goroutine并發中,我們可以通過使用通道,在多個goroutine發送和接受共享的數據,達到數據同步的目的。
### 通道,他有點像在兩個goroutine之間架設的管道,一個goroutine可以往這個管道里塞數據,另外一個可以從這個管道里取數據,有點類似于我們說的隊列。
`
通道的聲明方式 ch:=make(chan int)
`
### 通道類型和Map這些類型一樣,可以使用內置的 make 函數聲明初始化,這里我們初始化了一個 chan int 類型的通道,所以我們只能往這個通道里發送 int 類型的數據,當然接收也只能是 int 類型的數據。
### 通道是用于在goroutine之間通信的,它具有發送和接收兩個操作。
`ch <- 2 //發送數值2給這個通道
x:=<-ch //從通道里讀取值,并把讀取的值賦值給x變量
<-ch //從通道里讀取值,然后忽略
`
### 我們使用內置的 close 函數來關閉通道
### select總結
select是Go中的一個控制結構,類似于switch語句。select可以監聽多個channel的讀寫事件,當case中channel讀寫操作為非阻塞狀態(即能讀寫)時,將會觸發相應的動作。
1、如果有多個case都可以運行,select中對case語句的判斷不是順序進行的,select會隨機公平地選出一個執行,其他不會執行。
2、如果沒有可運行的case語句,且有default語句,那么就會執行default的動作。
3、如果沒有可運行的case語句,且沒有default語句,select將阻塞,直到某個case通信可以運行