企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
## 为什么需要管道 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) } ``` ![](https://img.kancloud.cn/a7/d3/a7d39340bfd77e4bc843094f6b579c54_397x165.png) ## interface chan 取出的时候需要类型断言,否则可以打印输出,但是无法获取内部的元素 ## 关闭管道 使用内置函数`close`,关闭后无法写入数据,但能读取数据 ## 遍历管道 for-range,不能使用普通的for ``` for v := range intChan2{ //没有下标index } ``` 1. 在遍历时,如果channel没有关闭,则会出现deadlock错误 2. 在遍历时,如果channel已经关闭,则会正常遍历数据,遍历完后,退出遍历