Go——Channel通道

一.介绍

        单纯的将函数并发执行是没有意义的。函数和函数之间需交换数据才能体现并发执行函数的意义。

        虽然可以使用共享内存来进行数据交换,但是共享内存在不同的goroutine中容易发送竞态问题。为了保证数据交换的正确性,必须使用互斥量对内存进行加锁,这种做法势必造成性能问题。

        Go语言的并发模型是CSP,提倡通过通信共享内存,而不是通过共享内存通信。

        如果说goroutine是Go程序并发的执行体,channel就是他们之间的连接。channel是可以让一个goroutine发送特定值到另外一个goroutine的通信机制。

        Go语言中的通道(channel)是一种特殊的类型。通道像一个传送带或者队列,总遵循先入先出的规则,保证收发数据的顺序。每一个通道都是一个具体类型的导管,也就是声明channel的时候需要为其指定元素类型。

二. channel类型

        channel是一种类型,一种引用类型。声明通道类型的格式如下:

var 遍历 chan 元素类型

         举几个例子:

var ch1 chan int //声明一个传递整型的通道
var ch2 chan bool //声明一个传递布尔型的通道
var ch3 chan []int //声明一个传递int切片的通道

三. 创建channel

         通道是引用类型,通道类型的默认值是nil。

        创建channel的格式如下:

make(chan 类型, 缓存大小)

        channel的缓存大小是可选的。

        举个例子:

ch1 := make(chan int)
ch2 := make(chan bool)
ch3 := make(chan, []int)

        四. channel操作

        通道有发送,接收核关闭三种操作。

        发送和接收都使用<-符号。关闭channel我们通过内置的close函数。

        关于关闭通道需要注意的是,只有在通知接收方goroutine所有数据都发送完毕时才需要关闭通道。通道可以被垃圾回收机制回收的,他和关闭文件是不一样的,在结束操作之后关闭文件是必须要做的,但关闭通道不是必须的。

        关闭后的通道有以下特点:

  • 对一个关闭的通道发送值会导致panic
  • 对一个关闭的通道接收值会一直获取值直到通道为空
  • 对一个关闭的并且没有值的通道执行接收操作会得到对应类型的默认值
  • 关闭一个已经关闭的通道会导致panic

        五. 无缓冲的通道

        创建无缓冲的通道:

make(chan 类型)
make(chan 类型, 0)

         无缓冲的通道又被称作阻塞的通道。

        为什么会出现deadlock错误呢?

        因为我们使用ch := make(chan int)创建的是无缓冲的通道,无缓冲的通道只有在有人接收值的时候才能发送值。无缓冲的通道必须有接收才能发送。否则会造成一直阻塞,导致死锁。

        解决:

        无缓冲通道上的发送操作会阻塞(先发送再接收),直到另外一个goroutine在该通道上执行接收操作,这时值才能发送成功,两个goroutine将继续执行。相反,(先接收再发送)如果接收方操作先执行,接收方的goroutine将阻塞,直到另外一个goroutine在该通道上发送一个值。

        使用无缓冲通道进行通信将导致发送和接收的goroutine同步化。因此,无缓冲通道也被称作同步通道。

         六. 有缓冲的通道

        创建有缓冲的通道:

make(chan 类型, 缓冲大小)

        只要通道的容量大于零,那么该通道就是有缓冲的通道,通道的容量表示通道中能存放的数量,容量满了会发生阻塞,直到有别的协程取出元素。

        我们可以使用内置的len函数获取通道中元素的数量,使用cap函数获取通道的容量。虽然我们很少这么做。

  七. close

        可以通过内置的close()函数关闭channel,如果你不往管道里存值或取值的时候一定记得关闭管道。

         八. 如何优雅的从通道中循环取值

        当通过通道发送有限数据时,我们可以通过close函数关闭通道来告知从该通道接收值的goroutine停止等待。

        当通道被关闭时,往该通道发送值会引发panic。当通道里没有数据时,从该通道里接收的值一直都是类型默认值。

        如何判断一个通道是否被关闭了呢?

        注意:对一个关闭的通道接收值会一直获取值直到通道为空,并且没有值的通道执行接收操作会得到对应类型的默认值。所以,我们需要判断一个通道是否关闭了。

package main

import "fmt"

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) //发送完数据之后,关闭ch1
	}()
	//开启goroutine从ch1中接收值,并将该值的平方发送到ch2中
	go func() {
		for {
			if v, ok := <-ch1; ok { //通道关闭后再取值 ok=false
				ch2 <- v * v
			} else {
				break
			}
		}
		close(ch2) //发送完数据之后,关闭ch2
	}()
	//在主协程中从ch2中接收值
	for data := range ch2 { //通道关闭会退出for range循环
		fmt.Println(data)
	}
}

        从上面的例子可以看出,有两种方式在接收值的时候判断通道是否关闭。

if data, ok := <- ch; ok{//通道关闭 ok=false
}

//常用
for data := range ch{//通道关闭,退出range
}

        九. 单向通道

        有的时候我们将通道作为参数在多个任务函数之间传递,很多时候我们在不同的任务函数中使用通道都会对其进行限制,比如限制通道在函数中只能发送或接收。

        Go语言提供了单向通道来处理这种情况。

        其中:

  • chan <- int是一个只能发送的通道,可以发送但是不能接收。即可以放值到该通道中,发送是相对于当前协程来说的。
  • <- chan int是一个只能接收的通道,可以接收但是不能发送。即可以从该通道中获取值,接收是相对于当前协程来说的。 

         在函数传参及任何赋值操作中,将双向通道转换为单向通道是可以的,但是反过来不可以

        十. 总结

        channel常见的异常总结:

        注意:关闭已经关闭的channel也会产生panic。 

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

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

相关文章

树莓派驱动开发--搭建环境篇(保姆级)

前言&#xff1a;树莓派的环境搭建关系到之后的驱动开发&#xff0c;故一个好的环境能让你顺手完成驱动开发&#xff01;我使用的是64位树莓派4b&#xff01;有显示屏的前提&#xff01;&#xff01;&#xff01;&#xff08;因为wifi连接太刁钻了&#xff09; 一、ubantu相关 …

(一)基于IDEA的JAVA基础14

在看今天的重点二维数组前&#xff0c;先做俩个练习复习一下&#xff0c;热热脑子: 求数组内的最大值/最小值 这个就是挨个比较换一下位置 假设有这么一组数组{16,48,48,54,3} public class Test01 { public static void main(String[] args) { int [] num {16,48,54,3}; …

【力扣】148. 排序链表

148. 排序链表 题目描述 给你链表的头结点 head &#xff0c;请将其按 升序 排列并返回 排序后的链表 。 示例 1&#xff1a; 输入&#xff1a;head [4,2,1,3] 输出&#xff1a;[1,2,3,4] 示例 2&#xff1a; 输入&#xff1a;head [-1,5,3,4,0] 输出&#xff1a;[-1,0,…

gma 2.0.8 (2024.04.12) 更新日志

安装 gma 2.0.8 pip install gma2.0.8网盘下载&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1P0nmZUPMJaPEmYgixoL2QQ?pwd1pc8 提取码&#xff1a;1pc8 注意&#xff1a;此版本没有Linux版&#xff01; 编译gma的Linux虚拟机没有时间修复&#xff0c;本期Linux版继…

.NET i18n 多语言支持与国际化

环境 WIN10 VS2022 .NET8 1.&#x1f44b;创建项目 2.&#x1f440;创建Resources Controllers HomeController.en.resx HomeController.fr.resx HomeController.zh.resx 3.&#x1f331;Program.cs添加国际化支持 // 添加国际化支持 builder.Services.AddLocalization(…

数据结构-链表刷题集(长期更新)

文章目录 1. leetcode 2 两数之和1.1 解法一 1. leetcode 2 两数之和 1.1 解法一 题目及其相关实例如下 要做这个题,首先我们要学会模拟竖式的加法,我们知道即使是java基本数据中最大的long类型范围也是有限的,那如果超出范围了我们该怎么办呢,我们就需要用字符串来模拟这个…

基于Java的XxlCrawler网络信息爬取实战-以中国地震台网为例

目录 前言 一、信息网站介绍 1、网站介绍 2、 地震历史信息 3、 历史信息接口分析 二、XxlCrawler组件 1、关于XxlCrawler 2、核心概念介绍 三、实际信息爬取 1、新建maven项目 2、新建model层对象 3、实际爬取 总结 前言 如今&#xff0c;只要谈起网络信息爬取也就…

配置交换机端口安全

1、实验目的 通过本实验可以掌握&#xff1a; 交换机管理地址配置及接口配置。查看交换机的MAC地址表。配置静态端口安全、动态端口安全和粘滞端口安全的方法。 2、实验拓扑 配置交换机端口安全的实验拓扑如图所示。 配置交换机端口安全的实验拓扑 3、实验步骤 &#xff…

set 类 和 map 类

1. 关联式容器 关联式容器也是用来存储数据的&#xff0c;与序列式容器不同的是&#xff0c;其里面存储的是<key, value>结构的 键值对&#xff0c;在数据检索时比序列式容器效率更高 2. 键值对 用来表示具有一一对应关系的一种结构&#xff0c;该结构中一般只包含…

JVM之JVM的基本介绍

基本介绍 JVM&#xff1a;全称 Java Virtual Machine&#xff0c;即 Java 虚拟机&#xff0c;一种规范&#xff0c;本身是一个虚拟计算机&#xff0c;直接和操作系统进行交互&#xff0c;与硬件不直接交互&#xff0c;而操作系统可以帮我们完成和硬件进行交互的工作 特点&…

Docker Image (镜像) 常见命令

Docker Image (镜像) 常用命令 docker images 功能&#xff1a;列出本地所有的镜像。如果镜像 ID 相同&#xff0c;但是 Tag 标签不同&#xff0c;也会被当作不同的条目被列出来。 语法&#xff1a; docker images [options] [REPOSITORY[:TAG]] 别名&#xff1a; docker ima…

【fastapi】搭建第一个fastapi后端项目

本篇文章介绍一下fastapi后端项目的搭建。其实没有什么好说的&#xff0c;按照官方教程来即可&#xff1a;https://fastapi.tiangolo.com/zh/ 安装依赖 这也是我觉得python项目的槽点之一。所有依赖都安装在本地&#xff0c;一旦在别人电脑上编写项目就又要安装一遍。很扯淡。…

mysql搭建主从

mysql搭建主从: 1:拉取mysql镜像 docker pull mysql2:创建主从对应目录 3:建立一个简易的mysql docker run -it --name mytest -e MYSQL_ROOT_PASSWORD123 -d mysql4:进入这个简易的mysql;从中获取my.cnf文件 docker exec -it mytest bash5:从容器中将my.cnf拷贝到 /3306/c…

ADC的认识

ADC介绍 Q:ADC是什么&#xff1f; A&#xff1a;全称&#xff1a;Analog-to-Digital Converter&#xff0c;指模拟/数字转换器 ADC的性能指标 量程&#xff1a;能测量的电压范围分辨率&#xff1a;ADC能辨别的最小模拟量&#xff0c;通常以输出二进制数的位数表示&#xf…

康耐视visionpro-CogBlobTool工具操作详细说明

CogBlobTool功能说明: 通过设置灰度值提取感兴趣区域,并分析所提取区域的面积、长宽等参数。 Cog BlobTool操作说明: .打开工具栏,双击或点击鼠标拖拽添加CogBlobTool工具 ②.添加输入图像:单击鼠标右键“链接到”或以连线拖拽的方式选择相应输入源 ③.极性: “白底黑点…

搭建基于Hexo的个人博客,以及git相关命令

全文写完之后的总结 测试命令 hexo clean hexo g hexo s 上传到服务器命令 hexo clean hexo g hexo d 上传到服务器&#xff08;如果上一个命令用不了&#xff09;&#xff0c;也要先hexo clean,hexo g git init git add . git commit -m "first commit" git p…

vscode配置c\c++及美化

文章目录 vscode配置c\c及美化1.安装vscode2.汉化3.安装c\c插件4.安装mingw5.配置mingw6. 运行c代码6.1 创建代码目录6.2 设置文件配置6.3 创建可执行任务&#xff1a;task.json6.4 编译执行6.5 再写其他代码6.6 运行多个c文件 7. 运行c文件8.调式代码8.1 创建launch.json8.2 修…

jenkins下载安装(mac)

下载官网 具体 直接命令安装 Sample commands: Install the latest LTS version: brew install jenkins-ltsStart the Jenkins service: brew services start jenkins-ltsRestart the Jenkins service: brew services restart jenkins-ltsUpdate the Jenkins version: brew u…

Requests,一个强大的 Python 库

Requests&#xff0c;一个强大的 Python 库 ​ 一. 介绍 在当今的互联网时代&#xff0c;网络数据的获取和处理变得尤为重要。无论是数据科学家获取数据集&#xff0c;还是开发者与外部API进行交互&#xff0c;都需要一个强大且易于使用的HTTP库来帮助完成这些任务。这就是r…

2024年认证杯数学建模挑战赛C题全解析

2024年认证杯C题的已经完成啦&#xff0c;包括参考论文&#xff0c;模型代码&#xff0c;分享给大家&#xff5e; 问题分析 对于这些问题&#xff0c;我们首先需要确定影响日光辐射降低效应的关键参数&#xff0c;例如海盐气溶胶的浓度、粒子大小、分布以及喷洒高度和范围。同…