Go 快速入门指南 - 通道方向和关闭通道
2022/12/29 4:24:03
本文主要是介绍Go 快速入门指南 - 通道方向和关闭通道,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
概述
建议先阅读 阻塞通道 和 非阻塞通道 小节。在前面的两个小节中, 为了最小化代码达到演示效果,省略了 关闭通道
的步骤, 正确的做法应该是在通道使用完成后关闭。
使用规则
通过关键字 clsoe
关闭通道。
-
- 关闭一个空的通道 (值为 nil) 时,panic
-
- 关闭一个非空 && 已关闭的通道时,panic
-
- 关闭一个非空 && 未关闭的通道时,正常关闭
这里的规则不必死记硬背,笔者遇到的大多数情况属于第二种,也就是 重复关闭一个通道
, 读者做到实际开发中遇到 关闭通道
的场景时,联系上下文,确认通道不会出现重复关闭的情况即可。
例子
关闭一个空的通道
package main func main() { var ch chan bool close(ch) } // $ go run main.go // 输出如下 /** panic: close of nil channel ... ... exit status 2 */
关闭一个非空 && 已关闭通道
package main func main() { ch := make(chan bool) close(ch) close(ch) // 重复关闭 } // $ go run main.go // 输出如下 /** panic: close of nil channel ... ... exit status 2 */
关闭一个非空 && 未关闭的通道
package main func main() { ch := make(chan bool) close(ch) println("channel closed") } // $ go run main.go // 输出如下 /** channel closed */
通道方向
通道的方向分为 发送
和 接收
。默认情况下,通道是双向的 (同时发送和接收),但是可以通过标识符指明通道为单向 (只读或只写)。
语法规则
可读写通道 (同时支持发送和接收)
变量 := make(chan 数据类型) # 例子 ch := make(chan string)
只读通道 (只支持接收)
变量 := make(<-chan 数据类型) # 例子 ch := make(<-chan string)
只写通道 (只支持发送)
变量 := make(chan<- 数据类型) # 例子 ch := make(chan<- string)
类型转换
双向通道可以转换为单向通道,但是单向通道无法转换为双向通道。
例子
package main // 参数是一个写入通道 func ping(pings chan<- string) { //<-pings // 错误: pings 通道只能写入 pings <- "hello world" } func pong(pings <-chan string, pongs chan<- string) { //pings <- "hello world" // 错误: pings 通道只能读取 //<-pongs // 错误: pongs 通道只能写入 msg := <-pings pongs <- msg } func main() { pings := make(chan string) pongs := make(chan string) done := make(chan bool) go ping(pings) go pong(pings, pongs) go func() { msg := <-pongs println(msg) done <- true }() <-done close(pings) close(pongs) close(done) } // $ go run main.go // 输出如下 /** hello world */
检测通道是否关闭
Go 语言没有提供函数或方法判断一个通道是否关闭。因此只能使用一个变通的办法:接收通道元素,根据返回的布尔值确定通道是否关闭。
例子
双向通道检测
package main func main() { ch := make(chan string) close(ch) if _, open := <-ch; !open { println("channel closed") } } // $ go run main.go // 输出如下 /** channel closed */
单向 (只读) 通道检测
package main import "time" func main() { ch := make(chan string) go func(c <-chan string) { if _, open := <-c; !open { println("channel closed") } }(ch) close(ch) time.Sleep(time.Second) } // $ go run main.go // 输出如下 /** channel closed */
单向 (只写) 通道检测
对于只写通道,需要采用一个折中的办法:
-
• 尝试向通道写入数据
-
• 如果写入成功,说明通道还未关闭
-
• 写入失败,发生
panic
, 这时可以利用defer
在recover
中输出原因
package main import "time" func main() { ch := make(chan string) go func(c chan<- string) { defer func() { if err := recover(); err != nil { // 捕获到 panic println("channel closed") } }() c <- "hello world" }(ch) close(ch) time.Sleep(time.Second) } // $ go run main.go // 输出如下,你的输出可能和这里的不一样 /** channel closed */
这篇关于Go 快速入门指南 - 通道方向和关闭通道的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-20go-zero 框架的 RPC 服务 启动start和停止 底层是怎么实现的?-icode9专业技术文章分享
- 2024-12-19Go-Zero 框架的 RPC 服务启动和停止的基本机制和过程是怎么实现的?-icode9专业技术文章分享
- 2024-12-18怎么在golang中使用gRPC测试mock数据?-icode9专业技术文章分享
- 2024-12-15掌握PageRank算法核心!你离Google优化高手只差一步!
- 2024-12-15GORM 中的标签 gorm:"index"是什么?-icode9专业技术文章分享
- 2024-12-11怎么在 Go 语言中获取 Open vSwitch (OVS) 的桥接信息(Bridge)?-icode9专业技术文章分享
- 2024-12-11怎么用Go 语言的库来与 Open vSwitch 进行交互?-icode9专业技术文章分享
- 2024-12-11怎么在 go-zero 项目中发送阿里云短信?-icode9专业技术文章分享
- 2024-12-11怎么使用阿里云 Go SDK (alibaba-cloud-sdk-go) 发送短信?-icode9专业技术文章分享
- 2024-12-10搭建个人博客网站之一、使用hugo创建个人博客网站