当前位置:网站首页>Go语言Channel理解使用
Go语言Channel理解使用
2022-06-10 22:48:00 【游戏编程】
首先我是从一个指导中看到一段话才想要来写这篇文章的,主要是一段容易让人误解的话,这里我直接把他的代码附上。也可以先看一些基础知识:
目录
基础
作用:用于在协程之间传递信息
类型:通道是引用类型,规则和切片相似,需要make
定义方式和操作:
var ch chan int//最后一个标识通道传递的元素类型make(chan 元素类型, [缓冲大小])ch <- n //写n <- ch //读close(ch)//关闭误解代码
代码的核心是两个线程以及连个无缓冲的通道。误会主要发生在下面的依据注释中**通道关闭后再取值ok=false**,对于他设置的无缓冲通道交换信息来说,可以是对的,但如果是有缓冲通道,则是明显的错误。下面我附上稍微修改的代码,二者对比就可明白。
package main//代码一import ( "fmt" //"time")func main() { ch1 := make(chan int) ch2 := make(chan int) // 开启goroutine将0~100的数发送到ch1中 go func() { for i := 0; i < 100; i++ { ch1 <- i } close(ch1) }() // 开启goroutine从ch1中接收值,并将该值的平方发送到ch2中 go func() { for { i, ok := <-ch1 // **通道关闭后再取值ok=false** if !ok { break } ch2 <- i * i } close(ch2) }() // 在主goroutine中从ch2中接收值打印 for i := range ch2 { // 通道关闭后会退出for range循环 fmt.Println(i) }}这是稍微修改的代码,可以看到修改了两处,溢出时把通道1换成了带缓冲的,一处时把关闭通道1的时刻换到i=50的时候,我们对比一下二者的执行结果:
修改代码和结果对比
package mainimport ( "fmt" //"time")func main() { ch1 := make(chan int,100)//改成了有缓冲的通道 ch2 := make(chan int) // 开启goroutine将0~100的数发送到ch1中 go func() { for i := 0; i < 100; i++ { ch1 <- i } }() // 开启goroutine从ch1中接收值,并将该值的平方发送到ch2中 go func() { for { i, ok := <-ch1 // 通道关闭后再取值ok=false if !ok { break } //修改处 if i == 50{ close(ch1) } ch2 <- i * i } close(ch2) }() // 在主goroutine中从ch2中接收值打印 for i := range ch2 { // 通道关闭后会退出for range循环 fmt.Println(i) }}

可以看到,虽然提前关闭了通道,但是因为有缓冲区的缘故,字符都是正常取出的,因为
i, ok := <-ch1 只要通道里有值存在返回的就是ok。关闭后虽然无法添加数据,但是通道取值是正常的,只有当元素被取完后才会返回false。其实他这么说能行得通的原因是无缓冲通道的原因,接受通道会一直阻塞知道发送方传值,通道中是不存有元素的。因此如果没有接收,不可以向一个无缓冲通道添加值。
单向通道
有的时候我们会将通道作为参数在多个任务函数间传递,很多时候我们在不同的任务函数中使用通道都会对其进行限制,比如限制通道在函数中只能发送或只能接收。
Go语言中提供了单向通道来处理这种情况:
可以在函数传参及任何赋值操作中将双向通道转换为单向通道。
package mainimport "fmt"//写通道func counter(out chan<- int) { for i := 0; i < 100; i++ { out <- i } close(out)}func squarer(out chan<- int, in <-chan int) { for i := range in { out <- i * i } close(out)}//读通道func printer(in <-chan int) { for i := range in { fmt.Println(i) }}func main() { ch1 := make(chan int) ch2 := make(chan int) go counter(ch1) go squarer(ch2, ch1) printer(ch2)}作者:Chinatesila
游戏编程,一个游戏开发收藏夹~
如果图片长时间未显示,请使用Chrome内核浏览器。
边栏推荐
- LabVIEW错误“内存已满 - 应用程序停止在节点”
- LabVIEW改变Point ROI Overlay的形状或颜色
- Top ten information security principles
- Leetcode-15 sum of three numbers
- 快速排序
- LabVIEW performs a serial loopback test
- [pyGame games] tank battle, how many childhood games do you remember?
- 【Pygame合集】滴~穿越童年游戏指南 请查收:这里面有你玩过的游戏嘛?(附五款源码自取)
- 希尔排序
- LabVIEW使用MathScript Node或MATLAB脚本时出现错误1046
猜你喜欢
![[pyGame] this](/img/7c/adc13c0c87ca31c8581d68e6f21363.jpg)
[pyGame] this "groundhog" game is going to be popular (come on, come on)

LabVIEW获取IMAQ Get Last Event坐标

【Pygame合集】回忆杀-“童年游戏”,看看你中几枪?(附五款源码自取)

LabVIEW使用MathScript Node或MATLAB脚本时出现错误1046

LabVIEW或MAX下的VISA测试面板中串口无法工作

LabVIEW图片在从16位强制转换为8位后看起来要亮或暗

【Opencv实战】这个印章“神器”够牛,节省了时间提高了效率,厉害~(附完整源码)

LabVIEW and VDM extract color and generate gray image

LabVIEW确定控件在显示器坐标系中的位置

curl导入postman报错小记
随机推荐
Vs tomato assistant add header comments and usage
【自动回复小脚本】新年快乐,每一个字都是我亲自手打的,不是转发哦~
【Opencv实战】这个印章“神器”够牛,节省了时间提高了效率,厉害~(附完整源码)
安全生产月,黄埔开展燃气安全进商铺宣传活动
MySQL命令行导入导出数据
【漫天烟花】绚烂烟花点亮夜空也太美了叭、某程序员携带烟花秀给大家拜年啦~
【Pygame小游戏】剧情流推荐:什么样的游戏才能获得大家的喜欢呢?(魔鬼恋人、霸总娇妻版)
Top ten information security principles
Compared with the "South-to-North Water Transfer", what will the "east to west" of the fire bring to cloud computing?
自制APP连接OneNET---实现数据监控和下发控制(MQTT)
CSDN daily practice - find the closest element and output the subscript
【LaTex】latex VS Code snippets(代码片段)
Method of converting file to multipartfile
[AI card player] for the first time to see such an "exciting" landowner, the key factor for a high winning rate is
集合删除元素技巧 removeIf
LabVIEW uses the visa read function to read USB interrupt data
[pyGame] this "groundhog" game is going to be popular (come on, come on)
【自动回复or提醒小助手】妈妈再也不用担心我漏掉消息了(10行代码系列)
都说验证码是爬虫中的一道坎,看我只用五行代码就突破它。
干货丨MapReduce的工作流程是怎样的?