【Go】十八、管道

news/2024/6/20 19:29:20/文章来源:https://blog.csdn.net/llg___/article/details/137268728

文章目录

  • 1、管道
  • 2、管道的定义
  • 3、管道的关闭
  • 4、管道的遍历
  • 5、管道 + 协程
  • 6、只读、只写管道
  • 7、管道的阻塞
  • 8、select

1、管道

  • channel
  • 本质是一个队列,先进先出
  • 自身线程安全,多协程访问时,不用加锁,channel本身就是线程安全的
  • 一个string的管道只能存放string类型数据

在这里插入图片描述

2、管道的定义

var  变量名  chan  数据类型
  • chan是管道的关键字
  • 数据类型,比如int类型的管道只能写入整数int
  • 管道是引用类型,必须初始化才能写入数据,即make后才能使用
  • 管道中不能存放大于容量的数据
  • 在没有使用协程的情况下,如果管道的数据已经全部取出,那么再取就会报错

示例:

package main
import("fmt"
)
func main(){//定义管道 、 声明管道 ---> 定义一个int类型的管道var intChan chan int//通过make初始化:管道可以存放3个int类型的数据intChan = make(chan int,3)//证明管道是引用类型:fmt.Printf("intChan的值:%v",intChan) // 0xc000112080//向管道存放数据:intChan<- 10num := 20intChan<- numintChan<- 40  //注意:不能存放大于容量的数据://intChan<- 80  //在管道中读取数据:num1 := <-intChannum2 := <-intChannum3 := <-intChanfmt.Println(num1)fmt.Println(num2)fmt.Println(num3)//注意:在没有使用协程的情况下,如果管道的数据已经全部取出,那么再取就会报错:num4 := <-intChanfmt.Println(num4)//输出管道的长度:fmt.Printf("管道的实际长度:%v,管道的容量是:%v",len(intChan),cap(intChan))
}

3、管道的关闭

使用内置函数close可以关闭管道,当管道关闭后,就不能再向管道写数据了,但是仍然可以从该管道读取数据

package main
import("fmt"
)
func main(){//定义管道 、 声明管道var intChan chan int//通过make初始化:管道可以存放3个int类型的数据intChan = make(chan int,3)//在管道中存放数据:intChan<- 10intChan<- 20//关闭管道:close(intChan)//再次写入数据:--->报错//intChan<- 30//当管道关闭后,读取数据是可以的:num := <- intChanfmt.Println(num)
}

4、管道的遍历

  • for
  • for-range

在遍历时,如果管道没有关闭,则报错:

在这里插入图片描述

package main
import("fmt"
)
func main(){//定义管道 、 声明管道var intChan chan int//通过make初始化:管道可以存放100个int类型的数据intChan = make(chan int,100)for i := 0;i < 100;i++ {intChan<- i}//在遍历前,如果没有关闭管道,就会出现deadlock的错误//所以我们在遍历前要进行管道的关闭close(intChan)//遍历:for-rangefor v := range intChan {fmt.Println("value = ",v)}
}

5、管道 + 协程

  • 开启一个writeData协程,向管道中写入50个整数.
  • 开启一个readData协程,从管道中读取writeData写入的数据

在这里插入图片描述

package main
import("fmt""time""sync"
)
var wg sync.WaitGroup //只定义无需赋值//写:
func writeData(intChan chan int){defer wg.Done()for i := 1;i <= 50;i++{intChan<- ifmt.Println("写入的数据为:",i)time.Sleep(time.Second)}//管道关闭:close(intChan)
}//读:
func readData(intChan chan int){defer wg.Done()//遍历:for v := range intChan{fmt.Println("读取的数据为:",v)time.Sleep(time.Second)}
}func main(){//主线程//写协程和读协程共同操作同一个管道-》定义管道:intChan := make(chan int,50)wg.Add(2)//开启读和写的协程:go writeData(intChan)go readData(intChan)//主线程一直在阻塞,什么时候wg减为0了,就停止wg.Wait()	
}

运行:
在这里插入图片描述

在没有使用协程的情况下,如果管道的数据已经全部取出,那么再取就会报错。所以上面即使写入后sleep两秒,读取也不会报错。

6、只读、只写管道

package main
import("fmt"
)
func main(){//默认情况下,管道是双向的--》可读可写://var intChan1 chan int//声明为只写:var intChan2 chan<- int  // 管道具备<- 只写性质intChan2 = make(chan int,3)intChan2<- 20//num := <-intChan2 报错fmt.Println("intChan2:",intChan2)//声明为只读:var intChan3 <-chan int// 管道具备<- 只读性质 if intChan3 != nil {	//非空num1 := <-intChan3fmt.Println("num1:",num1)}//intChan3<- 30 报错}

7、管道的阻塞

管道只写入数据,不读取,超过容量:

package main
import("fmt"_"time""sync"
)
var wg sync.WaitGroup //只定义无需赋值//写:
func writeData(intChan chan int){defer wg.Done()for i := 1;i <= 20;i++{   //超过容量管道的容量10intChan<- ifmt.Println("写入的数据为:",i)//time.Sleep(time.Second)}//管道关闭:close(intChan)
}func main(){//主线程//定义管道:intChan := make(chan int,10)wg.Add(1)//开启写的协程:go writeData(intChan)wg.Wait()	
}

在这里插入图片描述

改一下,写的快,读的慢:没报错,但很明显,写被影响了,到最后被动等读协程,读走一个,写协程才能继续写。

在这里插入图片描述

8、select

  • 从多个管道中进行非阻塞的选择
  • select同时监听多个管道的数据流通,并在其中任意一个管道有数据可读或者可写的时候做相应的处理
select {
case <- channel1:// 处理channel1的数据
case data := <- channel2:// 处理channel2的数据
case channel3 <- value:// 向channel3发送数据
default:// 当没有任何通道准备就绪时执行default块
}

按顺序检查有没那个case后面的管道是可读或者可写的,有则执行该case语句。如果多个case同时满足,Go会随机选择一个执行。

如果没有任何case语句满足条件,且存在default语句,则执行default块中的代码。如果没有default语句,则select语句会被阻塞,直到至少有一个case语句满足条件。

package main
import("fmt""time"
)
func main(){//定义一个int管道:intChan := make(chan int,1)go func(){time.Sleep(time.Second * 5)intChan<- 10}()//定义一个string管道:stringChan := make(chan string,1)go func(){time.Sleep(time.Second * 2)stringChan<- "msbgolang"}()//fmt.Println(<-intChan)//本身取数据就是阻塞的select{case v := <-intChan :fmt.Println("intChan:",v)case v := <-stringChan :fmt.Println("stringChan:",v)default:fmt.Println("防止select被阻塞")}
}

输出:

防止select被阻塞

上面两个case的协程都不能立即可读或可写,走了default。没有default,则输出:

msbgolang

因为其对应的管道阻塞时间短,2s后就可以读到了

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

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

相关文章

zabbix图表时间与服务器时间不一致问题

部署完zabbix后&#xff0c;有时候会发现zabbix服务器的时间明明是对的&#xff0c;但是图标的时间不对&#xff0c;通过以下的配置可以快速解决。 登录zabbix-nginx容器 docker exec -u root -it docker-compose-zabbix-zabbix-web-nginx-mysql-1 bash修改php配置文件 vi /e…

普通Java工程可执行JAR两种打包方式探讨

文章目录 一、需求概述二、代码结构三、运行结果四、打包设置1. 一体化可执行包2. 带外部依赖lib的可执行包 五、打包运行1. 源码放送2. 打包执行3. 打包结果 一、需求概述 普通Java工程 docker-show 实现了定时打印docker应用信息&#xff0c;现在需要将其打包成可执行Jar部署…

单元测试——Junit (断言、常用注解)

单元测试 Junit单元测试框架 使用 断言测试 使用Assert.assertEquals(message, 预期值, 实际值); 这段代码是用于在测试中验证某个方法的返回值是否符合预期。其中&#xff0c;"方法内部有bug"是用于在断言失败时显示的提示信息。4是预期的返回值&#xff0c;index…

Flutter应用混淆技术原理与实践

在移动应用开发中&#xff0c;保护应用代码安全至关重要。Flutter 提供了简单易用的混淆工具&#xff0c;帮助开发者在构建 release 版本应用时有效保护代码。本文将介绍如何在 Flutter 应用中使用混淆&#xff0c;并提供了相关的操作步骤和注意事项。 &#x1f4dd; 摘要 本…

4款在线网页原型图设计软件推荐

与桌面端相比&#xff0c;在线网页原型设计软件的使用具有优势&#xff0c;因为在线网页原型设计软件在整个使用过程中不需要安装&#xff0c;在线网页原型设计软件在任何地方都没有限制。更重要的是&#xff0c;无论是现在使用的 Linux&#xff0c;在线网页原型设计软件在操作…

LeetCode每日一题之专题一:双指针 ——移动零

移动零OJ链接&#xff1a;283. 移动零 - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 解法&#xff08;快排的思想&#xff1a;数组划分区间-数组分两块&#xff09;&#xff1a; 算法思路&#xff1a;在本题中&#xff0c;我们可以用一个 dest 指针来扫描整个数组…

第十五届蓝桥杯模拟考试I_物联网设计

反思&#xff1a; 本次模拟让我惊醒&#xff0c;写这个作品如同搭积木&#xff0c;在拼接的时候都要仔细检查这个积木是否出bug,确保没有问题再将其拼接到之前搭好的大模块之中&#xff0c;因为就是这样的题目我在处理过程中就遇到了BUG&#xff0c;原因竟出在输入模式要上拉&…

Vue3_2024_7天【回顾上篇watch常见的后两种场景】完

随笔&#xff1a;这年头工作不好找咯&#xff0c;大家有学历提升的赶快了&#xff0c;还有外出人多注意身体&#xff0c;没错我在深圳这边阳了&#xff0c;真的绝啊&#xff0c;最尴尬的还给朋友传染了&#xff01;&#xff01;&#xff01; 之前三种的监听情况&#xff0c;监听…

【c++】类和对象(七)

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 朋友们大家好&#xff0c;本篇文章来到类和对象的最后一部分 目录 1.static成员1.1特性 2.友元2.1引入&#xff1a;<<和>>的重载2.2友元函数2.3友元类 3.内部类4.匿名对象5.拷…

【Linux】在生产环境中,Linux系统排查常用命令

问题排查 文章目录 问题排查top命令CPU&#xff1a;vmstatprocscpu内存&#xff1a;free硬盘&#xff1a;df硬盘IO&#xff1a;iostat网络IO&#xff1a;ifstat 生产环境服务器变慢&#xff0c;诊断思路和性能评估 top命令 查看整机系统新能 使用top命令的话&#xff0c;重点…

Javascript/Node.JS中如何用多种方式避免属性为空(cannot read property of undefined ERROR)

>>>>>>问题 "cannot read property of undefined" 是一个常见的 JavaScript 错误&#xff0c;包含我在内很多人都会遇到&#xff0c;表示你试图访问一个未定义&#xff08;undefined&#xff09;对象的属性。这通常是因为你在访问一个不存在的对象…

【算法-PID】

算法-PID ■ PID■ 闭环原理■ PID 控制流程■ PID 比例环节&#xff08;Proportion&#xff09;■ PID 积分环节&#xff08;Integral&#xff09;■ PID 微分环节&#xff08;Differential&#xff09; ■ 位置式PID&#xff0c;增量式PID介绍■ 位置式 PID 公式■ 增量式 PI…

OpenCv —— cv::VideoCapture设置摄像头图像格式为“MJPEG“

背景 今天恰巧同事有台USB摄像头,她想要在Windows系统下通过OpenCV读取该摄像头宽高为1080x768、帧率为60的视频,用来做图像算法处理。但无奈通过网上OpenCV教程 读取的视频对应尺寸的帧率仅为10帧左右,根本无法满足使用要求。于是作者通过本篇文章介绍如何解决,欢迎交流指…

寒冬已逝,“量子春天”正来

最近&#xff0c;全球对量子技术领域的私人投资有所下降&#xff0c;引发了一些观点认为这个领域可能正逐渐衰退。 政治家、资助者和投资者并不总是以科学为关注焦点。然而&#xff0c;某些科技领域偶尔会成为热点&#xff0c;正如20世纪50年代核能技术的兴起&#xff0c;那时人…

如何开发创建自己的npm包并成功发布、维护至npm官方网站

npm&#xff0c;全称为Node Package Manager&#xff0c;是专为JavaScript生态系统设计的软件包管理系统&#xff0c;尤其与Node.js平台紧密关联。作为Node.js的默认包管理工具&#xff0c;npm为开发者提供了便捷的方式来安装、共享、分发和管理代码模块。 npm作为JavaScript世…

【Go】二十、反射

文章目录 1、反射2、对基本数据类型反射3、对结构体进行反射4、获取变量的类别5、通过反射修改基本类型变量的值6、通过反射操作结构体的属性和方法 1、反射 //核心包 import ("reflect")通过反射&#xff1a; 可以在运行时动态获取变量的类型、获取结构体的信息&a…

C++算法补充---STL

这里写目录标题 CSTL容器字符串函数(string容器函数)字符串转字符 算法交换函数拿到容器或者数组的第一个最大&#xff08;小&#xff09;值元素的下标或者值排序函数求字符数组的有效长度atoi函数&#xff08;将字符串类型的数字转为真正的int型数字&#xff09;string转字符 …

06 | Swoole 源码分析之 Coroutine 协程模块

首发原文链接&#xff1a;Swoole 源码分析之 Coroutine 协程模块 大家好&#xff0c;我是码农先森。 引言 协程又称轻量级线程&#xff0c;但与线程不同的是&#xff1b;协程是用户级线程&#xff0c;不需要操作系统参与。由用户显式控制&#xff0c;可以在需要的时候挂起、或…

【大模型】大模型 CPU 推理之 llama.cpp

【大模型】大模型 CPU 推理之 llama.cpp llama.cpp安装llama.cppMemory/Disk RequirementsQuantization测试推理下载模型测试 参考 llama.cpp 描述 The main goal of llama.cpp is to enable LLM inference with minimal setup and state-of-the-art performance on a wide var…

鸿蒙HarmonyOS应用开发之在非ArkTS线程中回调ArkTS接口

场景介绍 ArkTS是单线程语言&#xff0c;通过NAPI接口对ArkTS对象的所有操作都须保证在同一个ArkTS线程上进行。本示例将介绍通过napi_get_uv_event_loop和uv_queue_work实现在非ArkTS线程中通过NAPI接口回调ArkTS函数。 使用示例 接口声明、编译配置以及模块注册 接口声明 …