## 為什么需要管道
1. 主線程在等待所有goroutine全部完成的時間很難確定,比如設置10秒僅僅是估算
2. 如果主線程休眠時間長了,會加長等待時間;如果等待時間短了,可能還有goroutine處于工作狀態,這時也會隨主線程的退出而小灰
3. 通過全局變量加鎖來實現通訊,也并不利用多個協程對全局變量的讀寫操作
## 管道介紹
1. channel本質是一個數據結果-隊列
2. 數據是先進先出
3. 線程安全,多goroutine訪問時,不需要加鎖,就是說channel本身就是線程安全的
4. channel是有類型的,一個string的channel只能存放string類型數據
## 管道基本使用
```
var 變量名 chan 數據類型
var intChan chan int
var mapChan chan map[int]string
var perChan chan Person
var perChan1 chan *Person
```
1. channel是引用類型
2. channel必須初始化才能寫入數據,即make后才能使用
3. 管道是有類型的,只能寫入對應類型的數據
## 管道讀寫特性
1. 默認是可讀可寫
2. 聲明為只寫 `var chan2 chan<- int`
3. 聲明為只讀 `var chan3 <chan int`
4. 應用場景,函數內防止誤操作
## 示例代碼
```
package main
import (
"fmt"
)
func main() {
var intChan chan int
intChan = make(chan int, 3) //容量為3 int類型
? ? fmt.Printf("incChan的值=%v\\n", intChan) //地址
//向channel寫入數據,寫入的數據量不能超過管道的容量(cap)
intChan <- 10
num := 211
? ? intChan <- num
? ? fmt.Printf("channel len=%v cap=%v\\n", len(intChan), cap(intChan)) //len=2 cap=3
//從管道中讀取數據
num2 := <-intChan
? ? fmt.Printf("num2=%v channel len=%v cap=%v\\n", num2, len(intChan), cap(intChan)) //len=1 cap=3
//在沒有使用協程的情況下,如果管道數據已經全部取出,再取會報告deadlock
num3 := <-intChan
num4 := <-intChan
? ? fmt.Printf("num3=%v num4=%v", num3, num4)
}
```

## interface chan
取出的時候需要類型斷言,否則可以打印輸出,但是無法獲取內部的元素
## 關閉管道
使用內置函數`close`,關閉后無法寫入數據,但能讀取數據
## 遍歷管道
for-range,不能使用普通的for
```
for v := range intChan2{ //沒有下標index
}
```
1. 在遍歷時,如果channel沒有關閉,則會出現deadlock錯誤
2. 在遍歷時,如果channel已經關閉,則會正常遍歷數據,遍歷完后,退出遍歷
- 數據類型
- 數組array
- 切片slice
- 字符串string
- map
- 結構體struct
- 方法func
- 匿名結構體(繼承)
- 字段別名
- 接口interface
- 常量
- 基礎語法
- 循環for
- 遍歷
- 函數func
- defer
- 異常處理error
- 訪問范圍
- 包
- 類型斷言
- 文件
- 打開文件
- 讀取文件
- 寫文件
- 判斷是否存在
- 拷貝文件
- JSON
- 序列化
- 反序列化
- 命令行
- 雜項
- Windows下配置加速
- 相關鏈接
- 占位符
- 隨機數rand
- 單元測試
- goroutine
- 并發和并行
- 協程和主線程
- MPG模式
- 設置CPU數量
- 全局互斥鎖
- 管道
- 示例1
- 示例2
- select
- 異常捕獲
- 反射
- 示例
- 示例-改變值
- 網絡編程
- TCP編程
- 示例一
- redis