【Go】十八、管道

news2024/12/22 20:52:56

文章目录

  • 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<- 10
        num := 20
        intChan<- num
        intChan<- 40  
        //注意:不能存放大于容量的数据:
        //intChan<- 80  
        //在管道中读取数据:
        num1 := <-intChan
        num2 := <-intChan
        num3 := <-intChan
        fmt.Println(num1)
        fmt.Println(num2)
        fmt.Println(num3)
        //注意:在没有使用协程的情况下,如果管道的数据已经全部取出,那么再取就会报错:
        num4 := <-intChan
        fmt.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<- 10
        intChan<- 20
        //关闭管道:
        close(intChan)
        //再次写入数据:--->报错
        //intChan<- 30
        //当管道关闭后,读取数据是可以的:
        num := <- intChan
        fmt.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-range
        for 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<- i
                fmt.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 := <-intChan3
                fmt.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++{   //超过容量管道的容量10
                intChan<- i
                fmt.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.coloradmin.cn/o/1564505.html

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

相关文章

OpenCV 笔记(28):图像降噪算法——中值滤波、高斯滤波

1. 图像噪声 图像降噪(Image Denoising)是指从图像中去除噪声的过程&#xff0c;目的是提高图像质量&#xff0c;增强图像的视觉效果。 图像噪声是指图像中不希望出现的随机亮度或颜色变化&#xff0c;通常会降低图像的清晰度和可辨识度&#xff0c;以及会降低图像的质量并使图…

DFS:深搜+回溯+剪枝解决排列、子集问题

创作不易&#xff0c;感谢三连支持&#xff01;&#xff01; 一、全排列I . - 力扣&#xff08;LeetCode&#xff09; class Solution { public://全局变量vector<vector<int>> ret;vector<int> path;bool check[6];vector<vector<int>> perm…

【NLP】LLM 和 RAG

在这里&#xff0c;我描述了我在过去几年中关于 RAG 系统如何发展的主要经验。分享 Naive RAG、Advanced RAG 和 Modular RAG 框架之间的区别。总结了高云帆等人发表的一篇出色的RAG 技术调查论文的关键见解。 什么是 RAG 框架&#xff1f; OpenAI的GPT系列、Meta的LLama系列…

InterliJ IDEA基本设置

安装好idea后&#xff0c;将软件打开&#xff0c;可以进行基础设置 1.打开软件&#xff0c;先安装插件-汉化包&#xff08;不推荐&#xff0c;最好使用英文版&#xff09;&#xff0c;本次我们使用汉化版本完成基本设置&#xff0c;后期希望大家适应英文版的开发环境。&#x…

Databend 开源周报第 138 期

Databend 是一款现代云数仓。专为弹性和高效设计&#xff0c;为您的大规模分析需求保驾护航。自由且开源。即刻体验云服务&#xff1a;https://app.databend.cn 。 Whats On In Databend 探索 Databend 本周新进展&#xff0c;遇到更贴近你心意的 Databend 。 支持多表插入 …

一次MySQL事务的旅程:Buffer Pool, Binlog, Redo Log揭秘

MySQL中的各种Buffer和Log以及表空间 MySQL中一次事务涉及了各种Buffer,Log和表空间&#xff0c;主要涉及&#xff1a;Buffer Pool, Binlog, Undo Log, Redo Log以及表空间。 我们来探讨下。 Buffer Pool Buffer Pool主要存放在内存中&#xff0c;它是一个缓存区域&#xf…

论文阅读RangeDet: In Defense of Range View for LiDAR-based 3D Object Detection

文章目录 RangeDet: In Defense of Range View for LiDAR-based 3D Object Detection问题笛卡尔坐标结构图Meta-Kernel Convolution RangeDet: In Defense of Range View for LiDAR-based 3D Object Detection 论文&#xff1a;https://arxiv.org/pdf/2103.10039.pdf 代码&…

Python 与机器学习,在服务器使用过程中,常用的 Linux 命令包括哪些?

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 本博客旨在分享在实际开发过程中&#xff0c;开发者需要了解并熟练运用的 Linux 操作系统常用命令。Linux 作为一种操作系统&#xff0c;与 Windows 或 MacOS 并驾齐驱&#xff0c;尤其在服务器和开发环…

【Node.js从基础到高级运用】二十一、使用child_process模块创建子进程

引言 在Node.js中&#xff0c;child_process模块是一个提供了创建和管理子进程的能力的核心模块。通过使用child_process模块&#xff0c;Node.js可以执行系统命令、运行其他脚本或应用程序&#xff0c;实现与Node.js进程的并行处理。 child_process模块提供了几种创建子进程的…

环信IM集成教程——Web端UIKit快速集成与消息发送

写在前面&#xff1a; 千呼万唤始出来&#xff0c;环信Web端终于出UIKit了&#xff01;&#x1f389;&#x1f389;&#x1f389; 文档地址&#xff1a;https://doc.easemob.com/uikit/chatuikit/web/chatuikit_overview.html 环信单群聊 UIKit 是基于环信即时通讯云 IM SDK 开…

Docker:探索容器化技术,重塑云计算时代应用交付与管理

一&#xff0c;引言 在云计算时代&#xff0c;随着开发者逐步将应用迁移至云端以减轻硬件管理负担&#xff0c;软件配置与环境一致性问题日益凸显。Docker的横空出世&#xff0c;恰好为软件开发者带来了全新的解决方案&#xff0c;它革新了软件的打包、分发和管理方式&#xff…

聚观早报 | 蔚来推出油车置换补贴;iPhone 16 Pro细节曝光

聚观早报每日整理最值得关注的行业重点事件&#xff0c;帮助大家及时了解最新行业动态&#xff0c;每日读报&#xff0c;就读聚观365资讯简报。 整理丨Cutie 4月02日消息 蔚来推出油车置换补贴 iPhone 16 Pro细节曝光 小米SU7创始版第二轮追加开售 OpenAI将在日本设立办事…

OSPF中配置静态路由实验简述

静态路由协议和OSPF&#xff08;开放最短路径优先&#xff09;协议是两种常见的路由协议&#xff0c;它们在路由选择和网络管理方面有一些区别。他们可以共存。 静态路由协议需要手动配置路由表&#xff0c;不会自动适应网络拓扑变化&#xff0c;适用于小型网络或者网络拓扑变化…

图神经网络:处理非欧几里得数据的新视角

目录 1. 引言 2.图数据与图神经网络基础 3.GNN模型详解 4.应用案例 4.1. 社交网络分析 4.2. 化学分子性质预测 5.总结 1. 引言 非欧几里得数据指的是那些不遵循传统欧几里得空间几何规则的数据。在欧几里得空间中&#xff0c;数据点之间的距离和形状可以通过标准的几何度…

书生·浦语大模型(学习笔记-1)

一、大模型的发展 模型与通用人工智能&#xff08;AGI&#xff09;&#xff0c;大模型通常被视为发展通用人工智能的重要途径。AI研究从专用模型向通用模型转变&#xff0c;在过去的一二十年中&#xff0c;研究重点在于针对特定任务的专用模型。专用模型的已经再多个领域取得显…

试过了,ChatGPT确实不用注册就可以使用了!

看到官网说不用登录也可以直接使用ChatGPT 我们来试一下 直接打开官网 默认是直接进入了chatgpt3.5的聊天界面 之前是默认进的登录页面 聊一下试试 直接回复了&#xff0c;目前属于未登录状态&#xff0c;挺好&#xff01; 来试下ChatGPT4 跳转到了登录页面 目前来看gpt4还…

时序预测 | Matlab实现CPO-LSTM【24年新算法】冠豪猪优化长短期记忆神经网络时间序列预测

时序预测 | Matlab实现CPO-LSTM【24年新算法】冠豪猪优化长短期记忆神经网络时间序列预测 目录 时序预测 | Matlab实现CPO-LSTM【24年新算法】冠豪猪优化长短期记忆神经网络时间序列预测效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab实现CPO-LSTM【24年新算法】…

【Java+Springboot】----- 通过Idea快速创建SpringBoot项目操作方法

一、第一步&#xff1a; 点击选择【File】->【New】-> 【Project】 最后弹出[new Project]界面。 二、第二步&#xff1a; 1. 选择【Spring Initializr】 2. 然后选择【Project SDK】的版本 3. 然后 Choose Initializr Service URL 选择默认&#xff08;Default&#x…

OpenCV项目实战-深度学习去阴影-图像去阴影

往期热门博客项目回顾&#xff1a; 计算机视觉项目大集合 改进的yolo目标检测-测距测速 路径规划算法 图像去雨去雾目标检测测距项目 交通标志识别项目 yolo系列-重磅yolov9界面-最新的yolo 姿态识别-3d姿态识别 深度学习小白学习路线 //正文开始&#xff01; 图…

Python+requests+Pytest+logging+allure+pymysql框架详解

一、框架目录结构 1)tools目录用来放公共方法存储,如发送接口以及读取测试数据的方法,响应断言 数据库断言 前置sql等方法;2)datas目录用例存储接口用例的测试数据,我是用excel来存储的数据,文件数据 图片数据等;3)testcases目录用来存放测试用例,一个python文件对应…