极简的go语言channel入门

2024-09-03 10:28
文章标签 语言 go 入门 channel 极简

本文主要是介绍极简的go语言channel入门,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

写在文章开头

很久没写go语言相关的文章了,近期准备整理整理go语言channel相关的知识点,而本文将通过几个示例快速带读者了解channel的基本概念,希望对你有帮助。

在这里插入图片描述

Hi,我是 sharkChili ,是个不断在硬核技术上作死的 java coder ,是 CSDN的博客专家 ,也是开源项目 Java Guide 的维护者之一,熟悉 Java 也会一点 Go ,偶尔也会在 C源码 边缘徘徊。写过很多有意思的技术博客,也还在研究并输出技术的路上,希望我的文章对你有帮助,非常欢迎你关注我的公众号: 写代码的SharkChili

因为近期收到很多读者的私信,所以也专门创建了一个交流群,感兴趣的读者可以通过上方的公众号获取笔者的联系方式完成好友添加,点击备注 “加群” 即可和笔者和笔者的朋友们进行深入交流。

在这里插入图片描述

快速入门go语言channel基本概念

channel基础使用示例

作为一个java开发,笔者经常将channel的概念和阻塞队列进行关联,只不过两者在细节和理念上有些许区别,这里笔者先给出一个channel的基础示例,我们会往一个长度为1的channel中投递数据,然后从channel中取出数据并打印:

在这里插入图片描述

对应的代码如下所示,最终输出结果为:2024/08/31 10:07:22 receive data from the channel: hello world:

func main() {//声明一个channel,长度为1ch := make(chan string, 1)//往channel中投递数据ch <- "hello world"//取出channel数据s := <-ch//输出结果log.Println("receive data from the channel:", s)}

channel基础语法介绍

这里通过一个简单的示例了解的channel的使用,基于此示例我们进行一下语法拓展,如上所示,本质上channel的创建语法有两种:
第一种是make(chan type)这种就是所谓的无缓冲channel,这意味着投递到channel没有任何缓冲区,数据必须被即使处理掉才能投递新新数据:

在这里插入图片描述

对此我们再给出上一个代码的示例进行改造,将size去掉,这就是无缓冲channel的声明示例,运行时抛出了 all goroutines are asleep - deadlock!,很明显,因为无缓冲区的原因导致投递到channel的数据必须即使被消费,导致当前协程投递之后就无法往后走进而休眠,最终导致了死锁:

func main() {//声明一个无缓冲区channelch := make(chan string)//往channel中投递数据ch <- "hello world"//取出channel数据s := <-ch//输出结果log.Println("receive data from the channel:", s)}

channel的第二种语法就是我们最开始示例的有缓冲区channel,对应语法为make(chan type, size),需要注意的是如果size设置为0,那么channel仍然是个无缓冲区channel
接下来再说说channel数据的存取语法,如上文代码示例所示,对于存取go语言统一使用"<-",符号的左边即箭头所指向的就是消费者,右边是生产者,例如我们要往channel中投递数据,那么channel就是消费者,而我们的业务就是生产者,对应格式为:

channel<-data

相反,如果我们希望从channel中读取数据,那么我们的协程就是消费者,而channel就是生产者,那么语法就是反过来:

data<-channel

最后再说明一个特殊情况,其实go语言是支持丢弃channel数据的,还是以上述逻辑进行推理,因为我们要丢弃channel数据,那么channel就是生产者,因为数据要被丢弃,所以消费者为空,对应的语法为:

<-channel

channel主要解决什么问题

这里我们就来说明一下channelJava中阻塞队列不同的地方,按照go语言作者的设计理念,channel是用于解决一些并发中信号传递的,通过channel这个通信模型解耦协程间的通信,从而避免共享内存作为信号时协程竞争以及没必要的CPU资源占用。
举个共享内存的例子,我们现在有两个协程进行通信,协程1传到数字0时结束工作,按照共享内存的套路,我们会给协程1传入数字类型的指针,让协程1去轮询这个指针值的变化,直到数字变为1:

在这里插入图片描述

对此我们给出代码示例,可以看到主协程在休眠3s后修改sign的值,此时监听协程从sign的指针收到0值,由此退出循环。很明显这种做法会导致监听协程进行非必要的轮询进而消耗没必要的CPU资源,并且在高并发场景下为保证sign的并发有序,我们可能还需要通过各种互斥手段保护临界资源,这使得协程间的竞争开销变大,程序性能表现进一步降低:

func main() {//声明信号为1sign := 1//传入sign指针go listenCloseSignal(&sign)//休眠3s,修改sign的值time.Sleep(3 * time.Second)sign = 0time.Sleep(3 * time.Second)log.Println("execute over")
}func listenCloseSignal(sign *int) {for true {if *sign == 0 {log.Println("close go routine")break}}
}

取而代之我们使用channel,此时监听协程没有收到数据时就处于休眠状态,等到channel有数据才会被唤醒,又避免了非必要的空轮询开销而协程竞争开销,同时还能解耦模块间的逻辑,更有利于代码的扩展性和维护性:

func main() {ch := make(chan int)//传入sign指针go listenCloseSignal(ch)time.Sleep(3 * time.Second)ch <- 0time.Sleep(3 * time.Second)log.Println("execute over")
}func listenCloseSignal(ch chan int) {//监听channel的值sign := <-chif sign == 0 {log.Println("close go routine")}
}

而这就是设计们一直强调的:

用通道的方式共享内存,而不是共享内存进行通信

小结

自此,我们通过几个简单的案例介绍了channel的使用和注意事项,希望对你有帮助。

我是 sharkchiliCSDN Java 领域博客专家开源项目—JavaGuide contributor,我想写一些有意思的东西,希望对你有帮助,如果你想实时收到我写的硬核的文章也欢迎你关注我的公众号: 写代码的SharkChili
因为近期收到很多读者的私信,所以也专门创建了一个交流群,感兴趣的读者可以通过上方的公众号获取笔者的联系方式完成好友添加,点击备注 “加群” 即可和笔者和笔者的朋友们进行深入交流。

在这里插入图片描述

这篇关于极简的go语言channel入门的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1132713

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

Java 创建图形用户界面(GUI)入门指南(Swing库 JFrame 类)概述

概述 基本概念 Java Swing 的架构 Java Swing 是一个为 Java 设计的 GUI 工具包,是 JAVA 基础类的一部分,基于 Java AWT 构建,提供了一系列轻量级、可定制的图形用户界面(GUI)组件。 与 AWT 相比,Swing 提供了许多比 AWT 更好的屏幕显示元素,更加灵活和可定制,具有更好的跨平台性能。 组件和容器 Java Swing 提供了许多

【IPV6从入门到起飞】5-1 IPV6+Home Assistant(搭建基本环境)

【IPV6从入门到起飞】5-1 IPV6+Home Assistant #搭建基本环境 1 背景2 docker下载 hass3 创建容器4 浏览器访问 hass5 手机APP远程访问hass6 更多玩法 1 背景 既然电脑可以IPV6入站,手机流量可以访问IPV6网络的服务,为什么不在电脑搭建Home Assistant(hass),来控制你的设备呢?@智能家居 @万物互联

poj 2104 and hdu 2665 划分树模板入门题

题意: 给一个数组n(1e5)个数,给一个范围(fr, to, k),求这个范围中第k大的数。 解析: 划分树入门。 bing神的模板。 坑爹的地方是把-l 看成了-1........ 一直re。 代码: poj 2104: #include <iostream>#include <cstdio>#include <cstdlib>#include <al

MySQL-CRUD入门1

文章目录 认识配置文件client节点mysql节点mysqld节点 数据的添加(Create)添加一行数据添加多行数据两种添加数据的效率对比 数据的查询(Retrieve)全列查询指定列查询查询中带有表达式关于字面量关于as重命名 临时表引入distinct去重order by 排序关于NULL 认识配置文件 在我们的MySQL服务安装好了之后, 会有一个配置文件, 也就

Go Playground 在线编程环境

For all examples in this and the next chapter, we will use Go Playground. Go Playground represents a web service that can run programs written in Go. It can be opened in a web browser using the follow

go基础知识归纳总结

无缓冲的 channel 和有缓冲的 channel 的区别? 在 Go 语言中,channel 是用来在 goroutines 之间传递数据的主要机制。它们有两种类型:无缓冲的 channel 和有缓冲的 channel。 无缓冲的 channel 行为:无缓冲的 channel 是一种同步的通信方式,发送和接收必须同时发生。如果一个 goroutine 试图通过无缓冲 channel