Go-channel(管道)总结
特性
一个还未初始化的通道会被预置为nil(编译和运行时不会报错)
channel在使用时,需要使用make操作符,make会初始化通道,在内存中分配通道的空间。
关闭一个 nil 值 channel 会引发 panic。
package main func main() { var ch chan struct{} close(ch) }
关闭一个已关闭的 channel 会引发 panic。
package main func main() { ch := make(chan struct{}) close(ch) close(ch) }
向一个已关闭的 channel 发送数据。
package main func main() { ch := make(chan struct{}) close(ch) ch <- struct{}{} }
以上三种 channel 操作会引发 panic。 实际项目是很复杂的,一不小心,你就会忘了自己曾在哪一个 g 里关闭过 channel。
管道的读取
死锁
因为管道没有关闭 所以读取的时候 会一直阻塞当前读取 导致锁等待 造成死锁
package main import "fmt" func main() { ch := make(chan int, 8) ch <- 1 ch <- 2 //close(ch) fmt.Println(<-ch) //1 fmt.Println(<-ch) //2 //fmt.Println(<-ch)// }
返回零值
当从关闭的管道读取不到数据时,会返回管道类型的默认值比如 int 会返回 0
package main import "fmt" func main() { ch := make(chan int, 8) ch <- 1 ch <- 2 close(ch) fmt.Println(<-ch) //1 fmt.Println(<-ch) //2 fmt.Println(<-ch) //0 }
判断管道是否关闭
接收值和布尔值判断:
在接收 channel 的值时,可以使用多重赋值的方式接收两个值,一个是接收到的值,另一个是表示 channel 是否关闭的布尔值。如果 channel 已关闭且没有待接收的值,那么接收操作会立即返回并产生一个默认值。通过检查布尔值,可以判断 channel 是否已关闭。例如:
value, ok := <-ch if !ok { // channel 已关闭 }
使用 range
迭代:
可以使用 range
关键字来迭代 channel,当 channel 被关闭时,迭代会自动终止。可以通过检查循环中的布尔值来判断 channel 是否已关闭。例如:
for value := range ch { // 迭代 channel 的值 } // channel 已关闭
此外,还可以使用 select
语句结合 default
分支来判断 channel 是否关闭。当一个已关闭的 channel 没有待接收的值时,通过 select
语句的 default
分支可以立即执行对应的逻辑。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律