Golang使用Channel

1.使用协程

package main//使用协程
import ("fmt""strconv""time"
)func test() {for i := 1; i <= 10; i++ {fmt.Println("test() hello world" + strconv.Itoa(i))time.Sleep(time.Second)}
}// 主线程和test协程同时运行
func main() {go test() //开启了一个协程for i := 1; i <= 10; i++ {//strconv.Itoa函数:将整型转换为字符串fmt.Println("main() hello Golang" + strconv.Itoa(i))time.Sleep(time.Second)}
}
main() hello Golang1
test() hello world1
main() hello Golang2
test() hello world2
test() hello world3
main() hello Golang3
main() hello Golang4
test() hello world4
test() hello world5
main() hello Golang5
main() hello Golang6
test() hello world6
test() hello world7
main() hello Golang7
main() hello Golang8
test() hello world8
test() hello world9
main() hello Golang9
main() hello Golang10
test() hello world10

2.使用20个协程计算1到20各个数的阶乘,把结果放到map中

package mainimport ("fmt""sync""time"
)//计算1-20的各个数的阶乘,并且把各个数的阶乘放入到map中
//最后显示出来,要求使用goroutine完成//思路:1.编写一个函数,计算各个数的阶乘,并放入到map中
//2.我们启动的协程多个,统计的结果放入到map中
//3.map应该做出一个全局变量var (myMap = make(map[int]int, 20)//lock是一个全局的互斥锁//Mutex:互斥lock sync.Mutex
)func test(n int) {res := 1for i := 1; i <= n; i++ {res *= i}//把结果放入到map中//concurrent map writes//加锁lock.Lock()myMap[n] = reslock.Unlock()
}func main() {//开启多个协程完成这个任务for i := 1; i <= 20; i++ {go test(i)}//让主线程休眠,因为主线程执行完后,协程就会中止time.Sleep(time.Second * 5)//输出结果,遍历这个结果//lock.Lock()for i, v := range myMap {fmt.Printf("map[%d]=%d\n", i, v)}//lock.Unlock()
}
map[3]=6
map[7]=5040
map[10]=3628800
map[11]=39916800
map[19]=121645100408832000 
map[20]=2432902008176640000
map[13]=6227020800
map[9]=362880
map[16]=20922789888000     
map[4]=24
map[5]=120
map[6]=720
map[8]=40320
map[15]=1307674368000
map[18]=6402373705728000
map[17]=355687428096000
map[14]=87178291200
map[1]=1
map[2]=2
map[12]=479001600

3.Channel的使用

(1).Channel中只能存放指定的数据类型

(2).Channel数据放满后,就不能放入了

(3).如果从Channel中取出数据后,可以继续放入

(4).在没有使用协程的情况下,如果Channel数据取完了,再取,就会报dead lock

package mainimport "fmt"/**
Channel使用注意事项
1.Channel中只能存放指定的数据类型
2.Channel数据放满后,就不能放入了
3.如果从Channel中取出数据后,可以继续放入
4.在没有使用协程的情况下,如果Channel数据取完了,再取,就会报dead lock
*/
//演示管道需求
//channel相当于queuefunc main() {//1.创建一个存放3个int类型的管道var intChan chan int//capacity=3intChan = make(chan int, 3)//向管道写入数据intChan <- 10num := 211intChan <- num//4.看看管道的长度和容量fmt.Printf("channel len=%v cap=%v \n", len(intChan), cap(intChan))//5.从管道中读取数据var num2 intnum2 = <-intChanfmt.Println("num2=", num2)fmt.Printf("channel len=%v cap=%v \n", len(intChan), cap(intChan))
}
channel len=2 cap=3
num2= 10
channel len=1 cap=3

4.遍历管道

package mainimport "fmt"// 1.关闭管道,管道不能被写入数据,但是可以取出数据
func test1() {intChan := make(chan int, 3)intChan <- 100intChan <- 200close(intChan)intChan <- 300fmt.Println("Hello")}// 遍历管道
func test2() {intChan := make(chan int, 100)for i := 0; i < 100; i++ {intChan <- i * 2}//这个方法的前提是Channel要关闭,否则出现deadlockclose(intChan)for v := range intChan {fmt.Println("v=", v)}
}func main() {test2()
}

5.goroutine和channel协同工作案例

package mainimport ("fmt""time"
)/*
*
goroutine和channel协同工作案例
1.开启一个writeData协程,向管道intChan输入50个整数
2.开启一个readData协程,从管道intChan中读取writeData写入数据
3.writeData和readData操作的都是同一条管道
4.主线程需要等待writeData和readData协程都完成工作才退出
*/
func writeData(intChan chan int) {for i := 1; i <= 50; i++ {intChan <- itime.Sleep(time.Second)fmt.Println("writeData=", i)}close(intChan)
}
func readData(intChan chan int, exitChan chan bool) {for {v, ok := <-intChanif !ok {break}time.Sleep(time.Second)fmt.Println("readData=", v)}//读完数据后exitChan <- trueclose(exitChan)
}
func main() {intChan := make(chan int, 50)exitChan := make(chan bool, 1)go writeData(intChan)go readData(intChan, exitChan)//time.Sleep(time.Second * 10)for {_, ok := <-exitChanif ok {break}}
}
writeData= 1
readData= 1
readData= 2
writeData= 2
readData= 3
writeData= 3
readData= 4
writeData= 4
readData= 5
writeData= 5
readData= 6
writeData= 6
readData= 7
writeData= 7
readData= 8
writeData= 8
readData= 9
writeData= 9
readData= 10
writeData= 10
readData= 11
writeData= 11
readData= 12
writeData= 12
readData= 13
writeData= 13
readData= 14
writeData= 14
readData= 15
writeData= 15
readData= 16
writeData= 16
readData= 17
writeData= 17
readData= 18
writeData= 18
readData= 19
writeData= 19
readData= 20
writeData= 20
readData= 21
writeData= 21
readData= 22
writeData= 22
readData= 23
writeData= 23
readData= 24
writeData= 24
readData= 25
writeData= 25
readData= 26
writeData= 26
readData= 27
writeData= 27
readData= 28
writeData= 28
readData= 29
writeData= 29
readData= 30
writeData= 30
readData= 31
writeData= 31
readData= 32
writeData= 32
readData= 33
writeData= 33
readData= 34
writeData= 34
readData= 35
writeData= 35
readData= 36
writeData= 36
readData= 37
writeData= 37
readData= 38
writeData= 38
readData= 39
writeData= 39
readData= 40
writeData= 40
readData= 41
writeData= 41
readData= 42
writeData= 42
readData= 43
writeData= 43
readData= 44
writeData= 44
readData= 45
writeData= 45
readData= 46
writeData= 46
readData= 47
writeData= 47
readData= 48
writeData= 48
readData= 49
writeData= 49
readData= 50
writeData= 50

6.协程求素数

package mainimport ("fmt""time"
)//协程求素数
//要求统计1-200的数字中,哪些是素数?// 使用并行的方式,将统计素数的任务分配给多个(4个)goroutine去完成
func putNum(intChan chan int) {for i := 1; i <= 200; i++ {intChan <- i}//关闭close(intChan)
}// 从intChan取出数据,判断是否为素数,如果是,就放入到primeChan
func primeNum(intChan chan int, primeChan chan int, exitChan chan bool) {for {num, ok := <-intChanif !ok {break}flag := truefor i := 2; i < num; i++ {if num%i == 0 {flag = falsebreak}}if flag {//放入素数管道primeChan <- num}}fmt.Println("有一个primeNum协程因为取不到数据,退出")//这里我们还不能关闭primeChan//向exitChan写入trueexitChan <- true
}func main() {intChan := make(chan int, 1000)//放入结果primeChan := make(chan int, 10000)//标识退出的管道exitChan := make(chan bool, 4)start := time.Now().Unix()//开启一个协程,向intChan放入1-8000个数go putNum(intChan)//开启4个协程向intChan取出数据并判断是否为素数//如果是素数直接放入primeChanfor i := 0; i < 4; i++ {go primeNum(intChan, primeChan, exitChan)}go func() {//这里主线程要进行处理for i := 0; i < 4; i++ {<-exitChan}//从exitChan取出了4个结果,可以放心的关闭primeChanend := time.Now().Unix()fmt.Println("使用协程耗时=", end-start)close(primeChan)}()//遍历primeNum,把结果取出for {res, ok := <-primeChanif !ok {break}fmt.Printf("素数=%d\n", res)}fmt.Println("main()退出")
}
素数=1
素数=2                                
有一个primeNum协程因为取不到数据,退出
有一个primeNum协程因为取不到数据,退出
有一个primeNum协程因为取不到数据,退出
素数=3                                
有一个primeNum协程因为取不到数据,退出
使用协程耗时= 0                       
素数=5                                
素数=7                                
素数=11                               
素数=13                               
素数=17                               
素数=19                               
素数=23                               
素数=29                               
素数=31                               
素数=37                               
素数=41                               
素数=43                               
素数=47                               
素数=53                               
素数=59                               
素数=61                               
素数=67                               
素数=71
素数=73
素数=79
素数=83
素数=89
素数=97
素数=101
素数=103
素数=107
素数=109
素数=113
素数=127
素数=131
素数=137
素数=139
素数=149
素数=151
素数=157
素数=163
素数=167
素数=173
素数=179
素数=181
素数=191
素数=193
素数=197
素数=199
main()退出

7.使用select解决管道阻塞问题

package mainimport ("fmt"
)//使用select解决管道阻塞问题func main() {intChan := make(chan int, 10)for i := 0; i < 10; i++ {intChan <- i}stringChan := make(chan string, 5)for i := 0; i < 5; i++ {stringChan <- "hello" + fmt.Sprintf("%d", 5)}//传统的方法遍历管道,如果不关闭会阻塞,会遭遇deadlock//有可能不好确定什么时候关闭管道//使用select解决for {select {//注意:如果intChan一直没有关闭,不会一直阻塞而deadlock//会自动的到下一个casecase v := <-intChan:fmt.Println("从intChan读取数据 ", v)//time.Sleep(time.Second)case v := <-stringChan:fmt.Println("从stringChan读取数据 ", v)//time.Sleep(time.Second)default:fmt.Println("都读取不到了,不玩了")return}}
}

 8.goroutine中使用recover可以解决协程中出现panic

package mainimport ("fmt""time"
)// goroutine中使用recover可以解决协程中出现panic,导致程序崩溃问题
func sayHello() {for i := 0; i < 10; i++ {time.Sleep(time.Second)fmt.Println("Hello world")}}func test() {//这里我们使用defer+recoverdefer func() {//捕获test抛出的panic//捕获了以后,这个协程发生错误不影响其他协程if err := recover(); err != nil {fmt.Println("test() 发生错误", err)}}()//定义了一个map,让它发生错误var myMap map[int]stringmyMap[0] = "Golang" //error
}
func main() {go sayHello()//panic: assignment to entry in nil map//报错引起整个程序崩溃go test()for i := 0; i < 10; i++ {fmt.Println("main() ok=", i)time.Sleep(time.Second)}
}

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/80541.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用c++实现五子棋小游戏

五子棋是一款经典小游戏&#xff0c;今天我们就用c实现简单的五子棋小游戏 目录 用到的算法&#xff1a; 思路分析 定义变量 开始写代码 完整代码 结果图&#xff1a; 用到的算法&#xff1a; 合法移动的判断&#xff1a;isValidMove 函数通过检查指定位置是否在棋盘范…

游戏视频录制软件对比,哪款最适合你的需求?

随着电子竞技和游戏直播行业的迅速崛起&#xff0c;越来越多的玩家渴望记录并分享自己在游戏中的精彩瞬间。游戏视频录制软件正是满足这一需求的关键工具。本文将针对三款优秀的游戏视频录制软件进行对比分析&#xff0c;以便为读者提供选购建议。 游戏视频录制软件1&#xff1…

十天学完基础数据结构-第一天(绪论)

1. 数据结构的研究内容 数据结构的研究主要包括以下核心内容和目标&#xff1a; 存储和组织数据&#xff1a;数据结构研究如何高效地存储和组织数据&#xff0c;以便于访问和操作。这包括了在内存或磁盘上的数据存储方式&#xff0c;如何将数据元素组织成有序或无序的集合&…

RK3568-tftp更新设备树和内核nfs挂载文件系统

1. 注意:需要设备树和内核按以下修改才能支持tftp和nfs。 1.1 修改设备树: diff --git a/arch/arm64/boot/dts/rockchip/OK3568-C-linux.dts b/arch/arm64/boot/dts/rockchip/OK3568-C-linux.dts index 178b4d831..34cb57ffd 100644 --- a/arch/arm64/boot/dts/rockchip/OK…

go中之间的类型转换

一、字符串和切片之间的转换 >> 1 package main 2 3 …

C#调用python脚本教程使用pythonnet方式

本文介绍 C#使用pythonnet方式调用python脚本教程 目录 一、安装pythonnet 二、安装第三方库

移动端H5封装一个 ScrollList 横向滚动列表组件,实现向左滑动

效果&#xff1a; 1.封装组件&#xff1a; <template><div class"scroll-list"><divclass"scroll-list-content":style"{ background, color, fontSize: size }"ref"scrollListContent"><div class"scroll…

如何安装maatwebsite/excel?

背景 项目要下载内容&#xff0c;那最好是用扩展了&#xff0c;常用的也就是maatwebsite/excel,但是今天安装的提示异常 错误如下&#xff1a; Problem 1- maatwebsite/excel[3.1.28, ..., 3.1.30] require phpoffice/phpspreadsheet 1.16.* -> satisfiable by phpoffice/…

C# OpenVino Yolov8 Pose 姿态识别

效果 项目 代码 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Windows.Forms; using OpenCvSharp;namespace OpenVino_Yolov8_Demo {public…

独立开发了一款Material3风格的RSS阅读器 - Agr Reader

截图 背景&#x1f4d6; 在之前接触到RSS后&#xff0c;发现RSS真是一个十分不错的信息聚合的方式&#xff0c;虽然现在看来RSS的时代已经开始落幕&#xff0c;但是至少目前还是处于能用的阶段。 在我用了Android上好几个RSS阅读App后&#xff0c;发现很多在全文解析方面不是…

《Java核心技术卷1》学习笔记汇总

前言 转部门了&#xff0c;而且换语言了&#xff0c;开始写接口了&#xff0c;虽然也会用到CPP&#xff0c;但是主要语言是JAVA&#xff0c;因此从零开始学JAVA吧。 目录 Java程序设计描述Java程序设计环境Java的基本程序设计结构对象与类继承接口、lambda表达式与内部类异常…

Mapbox gl HTML经纬度点渲染,动态轨迹播放,自定义图形以及轨迹上显示箭头方向

Mapbox gl HTML经纬度点渲染&#xff0c;动态轨迹播放&#xff0c;自定义图形以及轨迹上显示箭头方向 1. 效果图2. 源码2.1 line.html2.2line_arrow.html 参考 今天要排查个问题&#xff0c;需要显示多个经纬度点连接成线段的方向&#xff0c;于是尝试下展示。 1. mapbox渲染经…

数据结构:栈

文章目录 栈一&#xff0c;概述二&#xff0c;添加数据三&#xff0c;删除数据 栈 一&#xff0c;概述 栈&#xff08;Stack&#xff09;是一种常见的数据结构&#xff0c;它是一种线性结构&#xff0c;具有特殊的添加和删除规则。栈的特性是后进先出&#xff08;LIFO&#x…

element plus封装el-select添加后缀图标并添加远程搜索和对话框功能

当提交的表单Form需要填某个实体的外键ID时&#xff0c;当然不可能使用el-input组件&#xff0c;这个适合提交字符串&#xff0c;然后用户又不可能记住某个引用的外键ID&#xff0c;这时候使用el-select还是必要的。 el-select组件一般都作为下拉选择框使用&#xff0c;但仅在…

远程计算机控制软件

远程控制软件允许您连接和控制位于不同位置的设备&#xff0c;对于 IT 帮助台技术人员来说&#xff0c;这是一个很好的工具&#xff0c;可以通过与用户协作、与他们聊天以及安全地访问他们的文件来轻松排除故障和修复远程设备。使用远程控制软件&#xff0c;距离不再是提供技术…

无涯教程-JavaScript - ATAN函数

描述 The ATAN function returns the arctangent, or inverse tangent, of a number. The returned angle is given in radians between -π/2 and π/2. The arctangent is the angle whose tangent is number. 语法 ATAN (number)争论 Argument描述Required/OptionalNumb…

Vulnhub实战-prime1

前言 VulnHub 是一个面向信息安全爱好者和专业人士的虚拟机&#xff08;VM&#xff09;漏洞测试平台。它提供了一系列特制的漏洞测试虚拟机镜像&#xff0c;供用户通过攻击和漏洞利用的练习来提升自己的安全技能。本次&#xff0c;我们本次测试的是prime1。 一、主机发现和端…

Jmeter性能实战之分布式压测

分布式执行原理 1、JMeter分布式测试时&#xff0c;选择其中一台作为调度机(master)&#xff0c;其它机器作为执行机(slave)。 2、执行时&#xff0c;master会把脚本发送到每台slave上&#xff0c;slave 拿到脚本后就开始执行&#xff0c;slave执行时不需要启动GUI&#xff0…

【机器学习】文本多分类

声明&#xff1a;这只是浅显的一个小试验&#xff0c;且借助了AI。使用的是jupyter notebook,所以代码是一块一块&#xff0c;从上往下执行的 知识点&#xff1a;正则删除除数字和字母外的所有字符、高频词云、混淆矩阵 参考&#xff1a;使用python和sklearn的中文文本多分类…

题目 1053: 二级C语言-平均值计算

输入10个整数&#xff0c;求它们的平均值&#xff0c;并输出大于平均值的数据的个数。 输出格式 大于平均数的个数 样例输入 1 2 3 4 5 6 7 8 9 10 样例输出 5 这题简单&#xff0c;直接创建数组&#xff0c;录入10个数。求累和再求平均数&#xff0c;之后for循环遍历数组…