当前位置: 首页 > news >正文

二十五、go语言的通道

目录

一、收发通信

二、将通道作为参数传递(读、写、读写)

三、select

1、先收到消息的先执行

2、一直没有收到消息退出通道

3、不知道何时退出情况下退出通道


go语言中的goroutine可以看成线程,但是又不能看成和其它语言一样的线程,因为在go语言中,goroutine之间的通信和其它语言不一样,例如如果在java中多条线程访问一个内存中数据在访问前需要进行加锁避免其它线程进入进行修改,本质上是通过共享了内存进行通信。而在go中是不一样的,在go中是“不要通过共享内存进行通信,而是通过通信来共享内存”

一、收发通信

import ("fmt""time"
)func receiver(c chan string) {for msg := range c {fmt.Println(msg)}
}
func main() {message := make(chan string, 2)message <- "hello"message <- "world"close(message)fmt.Println("push two message to channel")time.Sleep(time.Second * 2)receiver(message)
}

结果在2s中后输出

hello
world
解释

上述案例中 receiver函数接收了一个通道为string值的参数,并且进行循环输出

main方法中,mak(chan string,2)声明创建长度为2的通道

message <- "" 往通道内存入消息

close关闭通道意味着不可以再通过这个通道发送消息

调用receiver并传入message参数

二、将通道作为参数传递(读、写、读写)

在参数中<-在chan左边意味着可读,在右边意味着可写,没有意味着可读可写

func showReader(c <-chan string) {msg := <-cfmt.Println(msg)
}
func showWriter(c chan<- string) {c <- "hello world"
}func showReaderAndWriter(c chan string) {msg := <-cfmt.Println(msg)c <- "hello world"
}

在reader函数中,c是什么我们只能输出什么

在writer函数中,c是什么我们可以修改

在readerAndWriter函数中,c是什么我们可以输出什么也可以指定c是什么

三、select

1、先收到消息的先执行
func ping(c chan int) {time.Sleep(time.Second * 3)c <- 1
}
func ping2(c chan<- int) {time.Sleep(time.Second * 2)c <- 2
}
func main() {channel := make(chan int)channel2 := make(chan int)go ping(channel)go ping2(channel2)select {case msg := <-channel:fmt.Println(msg)case msg := <-channel2:fmt.Println(msg)}
}

结果:

2

解释L

在select中最先收到消息的执行后续代码,当创建两个ping方法时,ping sleep了3秒,ping2 sleep了2秒所以先执行了ping2

2、一直没有收到消息退出通道

当一直没有收到消息可以使用case <-time.After(time.Second * 3):

import ("fmt""time"
)func ping(c chan int) {time.Sleep(time.Second * 5)c <- 1
}
func ping2(c chan<- int) {time.Sleep(time.Second * 4)c <- 2
}
func main() {channel := make(chan int)channel2 := make(chan int)go ping(channel)go ping2(channel2)select {case msg := <-channel:fmt.Println(msg)case msg := <-channel2:fmt.Println(msg)case <-time.After(time.Second * 3):fmt.Println("timeout")}}
3、不知道何时退出情况下退出通道
import ("fmt""time"
)func sender(c chan string) {t := time.NewTicker(1 * time.Second)for {c <- "hello world"<-t.C}
}
func main() {messages := make(chan string)stop := make(chan bool)go sender(messages)go func() {time.Sleep(2 * time.Second)fmt.Println("time up")stop <- true}()for {select {case status := <-stop:fmt.Println(status)returncase msg := <-messages:fmt.Println(msg)}}
}

结果:

hello world
hello world
hello world
time up
true


解释:

 创建了一个sender方法,使用time.NewTicker(1 * time.Second),每一秒往通道中传递一次值

t := time.NewTicker(1 * time.Second)
for {c <- "hello world"<-t.C
}

在for循环中执行 

case msg := <-messages:fmt.Println(msg)

在接收到消息后执行,那么如果在没有手动终止程序的话就会一直执行

所以创建一个退出通道,当接收到true值时进行return,退出通道

case status := <-stop:fmt.Println(status)return

在同时并发执行一个func,并让这个程序sleep 2秒后,在给通道stop值为true

go func() {time.Sleep(2 * time.Second)fmt.Println("time up")stop <- true}()

所以在第一次并发调用

go sender(messages)

执行了一次

fmt.Println(msg)

此时func开始sleep 2秒,所以又执行了两次,当stop为ture时进行了return退出了通道

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 代码随想录算法训练营第32天|509. 斐波那契数、70. 爬楼梯、746. 使用最小花费爬楼梯
  • 8.28路虎女事件
  • 掌握 JavaScript 解构赋值的指南
  • 蜜罐网络MHN安装过程中的坑
  • Pytorch实现多层LSTM模型,并增加emdedding、Dropout、权重共享等优化
  • Windows 下载安装RabbitMQ
  • 干货分享:推荐四大在线翻译神器!
  • 26. 在集合中删除元素时,为什么使用Iterator.remove()而不是Collection.remove()?
  • GeoScene Pro教程(004):GeoScene Pro制作与使用矢量切片包
  • STL之string
  • 技术指南:5分钟零成本实现本地AI知识库搭建
  • vue3+vant4父组件点击提交并校验子组件form表单
  • 【区块链 + 司法存证】优证云:基于 FISCO BCOS 的存证平台 | FISCO BCOS应用案例
  • 【Python自动化办公】复制Excel数据:将各行分别重复指定次数
  • c++多线程下崩溃一例分析 ACTIONABLE_HEAP_CORRUPTION heap failure block not busy DOUBLE
  • Angular4 模板式表单用法以及验证
  • C# 免费离线人脸识别 2.0 Demo
  • CSS 专业技巧
  • C语言笔记(第一章:C语言编程)
  • JAVA并发编程--1.基础概念
  • k8s 面向应用开发者的基础命令
  • mysql中InnoDB引擎中页的概念
  • React中的“虫洞”——Context
  • v-if和v-for连用出现的问题
  • Wamp集成环境 添加PHP的新版本
  • 排序算法之--选择排序
  • 适配mpvue平台的的微信小程序日历组件mpvue-calendar
  • 数组的操作
  • 异常机制详解
  • 用 Swift 编写面向协议的视图
  • 在Unity中实现一个简单的消息管理器
  • 阿里云重庆大学大数据训练营落地分享
  • ​​​​​​​​​​​​​​Γ函数
  • #Linux杂记--将Python3的源码编译为.so文件方法与Linux环境下的交叉编译方法
  • #Ubuntu(修改root信息)
  • #我与Java虚拟机的故事#连载11: JVM学习之路
  • (06)金属布线——为半导体注入生命的连接
  • (20050108)又读《平凡的世界》
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (AngularJS)Angular 控制器之间通信初探
  • (Windows环境)FFMPEG编译,包含编译x264以及x265
  • (附源码)ssm捐赠救助系统 毕业设计 060945
  • (力扣题库)跳跃游戏II(c++)
  • (深入.Net平台的软件系统分层开发).第一章.上机练习.20170424
  • (一)Spring Cloud 直击微服务作用、架构应用、hystrix降级
  • .bat批处理(七):PC端从手机内复制文件到本地
  • .Net Core/.Net6/.Net8 ,启动配置/Program.cs 配置
  • .NET Framework与.NET Framework SDK有什么不同?
  • .NET/C# 编译期能确定的字符串会在字符串暂存池中不会被 GC 垃圾回收掉
  • .NET/C# 中设置当发生某个特定异常时进入断点(不借助 Visual Studio 的纯代码实现)
  • .NET建议使用的大小写命名原则
  • .net实现头像缩放截取功能 -----转载自accp教程网
  • .Net组件程序设计之线程、并发管理(一)
  • /etc/apt/sources.list 和 /etc/apt/sources.list.d
  • ??javascript里的变量问题