首页 > 其他分享 >Go 快速入门指南 - 通道方向和关闭通道

Go 快速入门指南 - 通道方向和关闭通道

时间:2022-12-24 18:33:01浏览次数:33  
标签:ch 入门 chan go 关闭 Go main 通道

概述

建议先阅读 阻塞通道 和 非阻塞通道 小节。在前面的两个小节中, 为了最小化代码达到演示效果,省略了 ​​关闭通道​​ 的步骤, 正确的做法应该是在通道使用完成后关闭。

使用规则

通过关键字 ​​clsoe​​ 关闭通道。

  1. 1. 关闭一个空的通道 (值为 nil) 时,panic
  2. 2. 关闭一个非空 && 已关闭的通道时,panic
  3. 3. 关闭一个非空 && 未关闭的通道时,正常关闭

这里的规则不必死记硬背,笔者遇到的大多数情况属于第二种,也就是 ​​重复关闭一个通道​​​, 读者做到实际开发中遇到 ​​关闭通道​​ 的场景时,联系上下文,确认通道不会出现重复关闭的情况即可。

例子

关闭一个空的通道

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 快速入门指南 - 通道方向和关闭通道_Go

标签:ch,入门,chan,go,关闭,Go,main,通道
From: https://blog.51cto.com/u_15915979/5967443

相关文章

  • Go 快速入门指南 - 遍历通道
    概述建议先阅读 range, 阻塞通道, 非阻塞通道 等小节。​​range​​ 除了可以遍历字符串、切片、数组等数据结构外,还可以遍历通道。语法规则和遍历其他数据结构不同,遍......
  • Go 快速入门指南 - 互斥锁和定时器
    互斥锁对于任一共享资源,同一时间保证只有一个操作者,这种方法称为 ​​互斥机制​​。关键字 ​​Mutex​​​ 表示互斥锁类型,它的 ​​Lock​​​ 方法用于获取锁,​​U......
  • django中间件
    django中间件相当于django框架的保安,只要数据过来必须经过中间件的校验。django中间件默认有7个。可以在setings内MIDDLEWARE里查看看着是字符串其实底层就是导模块的......
  • Gogs.02.构建本地仓库并上传到远程仓库
    01.通过VSCode构建一个Vue项目,npminitvue@latest配置参数并安装相关依赖  安装完成后,试运行一下,可以看到已还跑起来了; 02.本地仓构......
  • 使用PicGo+阿里云OSS实现md文档图片上传
    使用PicGo+阿里云OSS实现md文档图片上传这次给大家带来的是PicG0+阿里云Oss+typora的图床环境搭建,帮助大家提高工作效率+写博客速度!1.typora安装给大家一个链接:typora,打......
  • django中间件了解的三个方法、基于Django的插拔式设计、cookie与session简介、基于Dja
    目录Django中间件三个了解的方法1.process_view2.process_exception3.process_template_response基于Django中间实现功能的插拔式设计模拟编写一个消息通知功能(微信、qq、......
  • 红袖添香,绝代妖娆,Ruby语言基础入门教程之Ruby3基础数据类型(data types)EP02
    Ruby是强类型动态语言,即Ruby中一旦某一个对象被定义类型,如果不通过强制转换操作,那么它永远就是该数据类型,并且只有在Ruby解释器运行时才会检测对象数据类型,它的一切皆为对......
  • Go
    Chapter01编译器是全文翻译,解释器是实时翻译。1.环境搭建1.1MAC&Linux下载编译器:MAC:在golang.google.cn中点击DownloadGo,选择ApplemacOS即可,默认安装路径......
  • 1005.Django自定义过滤器及标签
    一、关于自定义自定义的引入内置函数--------->自定义函数内置模块--------->自定义模板内置过滤器------>自定义过滤器内置标签--------->自定义标签二、文件路径配......
  • 在Dubbo-go中使用TLS加密进行安全通信
    1背景Dubbo-go在Getty/Triple/Grpc三个通信层面支持TLS链路安全通信。2原理2.1证书机制:ps:可以先提前了解非对称加密机制。CA(CertificationAuthority)负责生成根证书......