Go语言现代web开发14 协程和管道
概述
Concurrency is a paradigm where different parts of the program can be executed in parallel without impact on the final result. Go programming supports several concurrency concepts related to concurrent execution and communication between concurrent executions.
并发是一种范例,其中程序的不同部分可以并行执行而不会影响最终结果。Go编程支持与并发执行和并发执行之间的通信相关的几个并发概念。
协程
A thread is a small sequence of instructions that can be processed by a single CPU core. Moder hardware architectures have multiple cores, so we can execute multiple threads in paralle.
线程是可以由单个CPU核心处理的一小段指令序列。现代硬件架构有多个内核,因此我们可以并行执行多个线程。
Go programming language offers its own solution for concurrent execution, called goroutines. Goroutines can be defined as lightweight threads (because they are very small, only a couple of KB will be used to store all thread-related data on the stack) managed by Go routine.
Go编程语言为并发执行提供了自己的解决方案,称为gooutines。Go例程可以定义为由Go例程管理的轻量级线程(因为它们非常小,只需要几个KB就可以将所有与线程相关的数据存储在堆栈上)。
If we use the go keyword in front of a function call, that function will be executed in a new goroutine, but the evaluation of arguments will be executed in the current goroutine. Here we have two function calls, the first one will be executed in the current goroutine and for the second one, a new goroutine will be created.
如果我们在函数调用前使用go关键字,那么该函数将在新的运行例程中执行,但参数的计算将在当前运行例程中执行。这里我们有两个函数调用,第一个将在当前的运行例程中执行,第二个将创建新的运行例程。
sendMessage(message1)
go sendMessage(message2)
Goroutines run in the same address space so, in certain situations, goroutines must synchronize memory access and communicate with each other.
运行在相同的地址空间中,因此,在某些情况下,运行例程必须同步内存访问并相互通信。
完整示例代码:
package mainimport ("fmt""time"
)func sendMessage(msg string) {fmt.Println(msg)
}func main() {sendMessage("hello, Mara!")// main goroutine 一旦执行结束,其他goroutine不再执行,被迫结束go sendMessage("Hi, Mara!")// 方法1:延长main的执行时间time.Sleep(time.Second)
}
管道
We can define the channel as a construct through which we can send and receive values. In order to send or receive value, we will use the <-
(arraow) operator in the following way:
ch <- value
will send value to channel chvalue = <- ch
will receive value from channel ch
我们可以将管道定义为可以发送和接收值的构造。为了发送或接收值,我们将以以下方式使用<-
(箭头)操作符:
ch <- value
将发送值到管道chvalue = <- ch
将从管道ch接收值
As can be seen, the data flow is determined by the direction of the arrow.
可以看出,数据流是由箭头方向决定的。
We have two types of channels:
- Unbuffered without buffer for message storage
- Buffered with buffer for message storage
我们有两种管道:
- 不带缓存的管道,没有缓存存储消息
- 带缓存的管道,通过缓存存储消息
By default, the channel is unbuffered with send and receive as blocking operations. The sender will be blocked until the receiver is ready to pick up the variable from the channel and vice versa. The receiver will be blocked, waiting for the value until the sender sends it to the channel. This can be very useful because there is no need for any additional synchronization.
默认情况下,管道是无缓冲的,发送和接收都是阻塞操作。发送方将被阻塞,直到接收方准备好从通道中获取变量,反之亦然。接收方将被阻塞,等待该值,直到发送方将其发送到通道。这非常有用,因为不需要任何额外的同步。
Traditionally, we use the make() function to create a channel. This will create a new channel that allows us to send and receive string variables.
传统上,我们使用make()函数来创建管道。下面的示例将创建一个允许我们发送和接收字符串变量的新管道。
ch := make(chan string)
Through the channels which we have dealt so far, we can send only one value. But in practice, this is not an acceptable solution, for example, if the sender is faster than the receiver, the sender will be blocked too often. We can avoid that by defining a buffer, now we can accept more variables. Channels with buffers are called buffered channels.
对于我们刚才创建的管道,我们只能发送一个值。但在实践中,这不是一个可接受的解决方案,例如,如果发送方比接收方快,发送方就会经常被阻塞。我们可以通过定义缓冲区来避免这种情况,现在我们可以接受更多的变量。具有缓冲区的通道称为缓冲通道。
A buffered channel will be created by adding buffer size as a second parameter in the make() function.
通过在make()函数中添加缓冲区大小作为第二个参数来创建缓冲通道。
ch = make(chan string, 100)
With the buffered channel, the sender will be blocked only when the buffer is full and the receiver will be blocked only when the buffer is full and the receiver will be blocked only when the buffer is empty. In the next code example, we will use the bufferedchannel to send two messages from new goroutines and receive those messages in the main goroutine.
对于缓冲通道,只有当缓冲区已满时发送方才会被阻塞,只有当缓冲区为空时接收方才会被阻塞。在下一个代码示例中,我们将使用bufferedchannel从新的运行例程发送两条消息,并在主运行例程中接收这些消息。
func sendMessage(message string, ch chan string) {ch <- message
}func main() {ch := make(chan string, 2)go sendMessage("Hello", ch)go sendMessage("World", ch)fmt.Println(<-ch)fmt.Println(<-ch)
}
We cannot influence which goroutine will send the message first, words Hello and World will not always be displayed in that order on standard output.
我们无法影响哪个程序将首先发送消息,单词Hello和World在标准输出中并不总是按该顺序显示。
The sender and only the sender can close the channel when there are no more values to send by calling the close() function.
当没有更多的值可以发送时,只有发送方可以通过调用close()函数关闭通道。
close(ch)
The receiver should check if the channel is closed. In the following expression, variable ok will have the value false when the channel is closed.
接收端应该检查信道是否关闭。在下面的表达式中,当通道关闭时,变量ok的值为false。
v ok <- ch
Constant checking an be tiresome, but luckily, a special kind of for range loop can be used. If we put the channel in for range, the loop will receive values until the channel is closed.
不断的检查是令人厌烦的,但幸运的是,一种特殊的范围循环可以使用。如果我们将通道设置为for range,循环将接收值,直到通道关闭。
for v := range ch {fmt.Println(v)
}
If we try to send a message to a closed channel, panic will be triggered. When panic occurs, a message will be displayed on standard output and the function where panic has occurred with crash.
如果我们试图向封闭通道发送信息,就会引发panic异常。当panic发生时,将在标准输出和发生panic的函数上显示一条消息并崩溃。
In all of our previous examples, the receiver waits on only one channel, but Go provides us with the concept that allows the receiver to wait on multiple channels: select statement. Syntatically, select statement is similar to be switch statement, with one differece, keyword select is used instead of keyword switch. The receiver will be blocked until one of the case statements can be executed.
在前面的所有示例中,接收方只在一个通道上等待,但是Go为我们提供了select语句,允许接收方在多个通道上等待。从语法上讲,select语句与switch语句类似,区别在于使用关键字select而不是关键字switch。接收方将被阻塞,直到其中一个case语句可以执行。
select{case <- ch1:fmt.PPrintln("Channel One")case <- ch2:fmt.Println("Channel Two")default:fmt.Println("Waiting")
}
A default case will be executed if no other case isready.
如果没有准备好其他情况,将执行默认情况。
相关文章:

Go语言现代web开发14 协程和管道
概述 Concurrency is a paradigm where different parts of the program can be executed in parallel without impact on the final result. Go programming supports several concurrency concepts related to concurrent execution and communication between concurrent e…...

Llama3.1的部署与使用
✨ Blog’s 主页: 白乐天_ξ( ✿>◡❛) 🌈 个人Motto:他强任他强,清风拂山冈! 💫 欢迎来到我的学习笔记! 什么是Llama3.1? Llama3.1 是 Meta(原 Facebook)公…...

Java/Spring项目的包开头为什么是com?
Java/Spring项目的包开头为什么是com? 下面是一个使用Maven构建的项目初始结构 src/main/java/ --> Java 源代码com.example/ --->为什么这里是com开头resources/ --> 资源文件 (配置、静态文件等)test/java/ --> 测试代码resourc…...

深度学习自编码器 - 随机编码器和解码器篇
序言 在深度学习领域,自编码器作为一种无监督学习技术,凭借其强大的特征表示能力,在数据压缩、去噪、异常检测及生成模型等多个方面展现出独特魅力。其中,随机编码器和解码器作为自编码器的一种创新形式,进一步拓宽了…...

Spring IoC DI
Spring 框架的核心是其控制反转(IoC,Inversion of Control)和依赖注入(DI,Dependency Injection)机制。这些概念是为了提高代码的模块化和灵活性,进而简化开发和测试过程。下面将详细介绍这两个…...

[数据集][目标检测]无人机飞鸟检测数据集VOC+YOLO格式6647张2类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):6647 标注数量(xml文件个数):6647 标注数量(txt文件个数):6647 标注…...

Vue 中 watch 的使用方法及注意事项
前言 Vue 的 Watch 是一个非常有用的功能,它能够监听 Vue 实例数据的变化并执行相应的操作。本篇文章将详细介绍 Vue Watch 的使用方法和注意事项,让你能够充分利用 Watch 来解决 Vue 开发中的各种问题。 1. Watch 是什么? 1.1 Watch 的作…...

情指行一体化平台建设方案和必要性-———未来之窗行业应用跨平台架构
一、平台建设必要性 以下是情指行一体化平台搭建的一些必要性: 1. 提高响应速度 - 实现情报、指挥和行动的快速协同,大大缩短从信息获取到决策执行的时间,提高对紧急情况和突发事件的响应效率。 2. 优化资源配置 - 整合各类资源信…...

窗口框架frame(HTML前端)
一.窗口框架 作用:将网页分割为多个HTML页面,即将窗口分为多个小窗口,每个小窗口可以显示不同的页面,但是在浏览器中是一个完整的页面 基本语法 <frameset cols"" row""></frameset><frame…...

51单片机——数码管
一、数码管原理图 我们发现,总共有8个数码管。 它们的上面接8个LED,用来控制选择哪个数码管。例如要控制第三个数码管,就让LED6为0,其他为1,那LED又接到哪呢? 二、LED 由图可以看出,这个一个1…...

`re.compile(r“(<.*?>)“)` 如何有效地从给定字符串中提取出所有符合 `<...>` 格式的引用
regexp re.compile(r"(<.*?>)") 这行代码是在Python中使用正则表达式的一个示例,具体含义如下: re.compile(): 这个函数来自Python的 re(正则表达式)模块,用于将一个正则表达式模式编译成一个正则表…...

算法打卡:第十一章 图论part01
今日收获:图论理论基础,深搜理论基础,所有可达路径,广搜理论基础(理论来自代码随想录) 1. 图论理论基础 (1)邻接矩阵 邻接矩阵存储图,x和y轴的坐标表示节点的个数 优点…...

为C#的PetaPoco组件增加一个批量更新功能(临时表模式)
总有一些数据是需要批量更新的,并且更新的字段,每个数据都不一样。 为了实现这样一个功能,写了这样一个方法: using System.Linq.Expressions; using System.Reflection; using System.Text; using NetRube.Data; using PetaPoc…...

Spring实战——入门讲解
博客主页: 南来_北往 系列专栏:Spring Boot实战 Spring介绍 Spring实战的入门讲解主要涵盖了Spring框架的基本概念、核心功能以及应用场景。以下是关于Spring实战入门的具体介绍: Spring框架概述:Spring是一个轻量级的Java开发框架…...

MTK芯片机型的“工程固件” 红米note9 5G版资源预览 写入以及改写参数相关步骤解析
小米机型:小米5 小米5x 米6 米6x 米8 米9 米10系列 米11系列 米12系列 mix mix2 mix2s mix3 max max2 max3 note3 8se 9se cc9系列 米play 平板系列等分享 红米机型:红米note4 红米note4x 红米note5 红米note6 红米note7 红米note8 红米note8pro 红米s2 红米note7pro 红米…...

[Golang] Context
[Golang] Context 文章目录 [Golang] Context什么是context创建context创建根context创建context context的作用并发控制context.WithCancelcontext.WithDeadlinecontext.WithTimeoutcontext.WithValue 什么是context Golang在1.7版本中引入了一个标准库的接口context…...

【JAVA集合总结-壹】
文章目录 synchronized 的实现原理以及锁优化?ThreadLocal原理,使用注意点,应用场景有哪些?synchronized和ReentrantLock的区别?说说CountDownLatch与CyclicBarrier 区别Fork/Join框架的理解为什么我们调用start()方法…...

Mysql梳理7——分页查询
目录 7、分页查询 7.1 背景 7.2 实现规则 分页原理 7.3 使用 LIMIT 的好处 7、分页查询 7.1 背景 背景1:查询返回的记录太多了,查看起来很不方便,怎么样能够实现分页查询呢? 背景2:表里有 4 条数据,…...

智能制造与工业互联网公益联播∣企企通副总经理杨华:AI的浪潮下,未来智慧供应链迭代方向
近两年在IT圈子里面,AI毫无疑问是最火的一个词语,最近的ChatGPT、文心一言、通义千问,从千亿参数到万亿参数,再往前就是Sora文生视频异军突起... 在人工智能的浪潮下,AI之于供应链的价值体现在哪些地方?其发…...

《深度学习》—— 卷积神经网络(CNN)的简单介绍和工作原理
文章目录 一、卷积神经网络的简单介绍二、工作原理(还未写完)1.输入层2.卷积层3.池化层4.全连接层5.输出层 一、卷积神经网络的简单介绍 基本概念 定义:卷积神经网络是一种深度学习模型,通常用于图像、视频、语音等信号数据的分类和识别任务。其核心思想…...

数据结构:线性表
1、线性表概述 1.1线性表的定义 线性表(list):零个或多个数据元素的有限序列。 简单地来说,我们可以用下面这张图来描述一个线性表: 1.2 线性表的存储结构 1.2.1顺序存储结构——顺序表 顺序表是将数据全部存储到…...

Ansible PlayBook实践案例
一、PlayBook介绍 1.什么是playbook playbook 顾名思义,即剧本,现实生活中演员按照剧本表演,在 ansible 中,由被控计算机表演,进行安装,部署应用,提供对外的服务等,以及组织计算机处理各种各样…...

Tomcat后台弱口令部署war包
1.环境搭建 cd /vulhub/tomcat/tomcat8 docker-compose up -d 一键启动容器 2.访问靶场 点击Manager App tomcat8的默认用户名和密码都是tomcat进行登录 3.制作war包 先写一个js的一句话木马 然后压缩成zip压缩包 最后修改后缀名为war 4.在网站后台上传war文件 上传war文件…...

胤娲科技:DeepMind的FermiNet——带你穿越“薛定谔的早餐桌”
当AI遇上量子迷雾,FermiNet成了你的“量子导航仪” 想象一下,你早晨醒来,发现家里的厨房变成了薛定谔的实验室,你的咖啡杯和吐司同时处于“存在与不存在”的叠加态。 你伸手去拿,却不确定会不会摸到冰冷的空气或是热腾…...

迅为iTOP-STM32MP157开发板板载4G接口(选配)_千兆以太网_WIFI蓝牙模块_HDMI_CAN_RS485_LVDS接口等
迅为ITOP-STM32MP157是基于ST的STM32MP157芯片开发的一款开发平台。在STM32MP157开发平台上,我们也做了比较多的创新,其中重要的一点就是,iTOP-STM32MP157核心板电源管理采用ST全新配套研制的PMIC电源管理芯片STPMU1A。为整个系统的稳定运行提…...

Android Choreographer 监控应用 FPS
Choreographer 是 Android 提供的一个强大的工具类,用于协调动画、绘制和视图更新的时间。它的主要作用是协调应用的绘制过程,以确保流畅的用户体验。Choreographer 也可以帮助我们获取帧时间信息,从而为性能监测和优化提供重要的数据支持。 …...

关于 mybatis-plus-boot-starter 与 mybatis-spring-boot-starter 的错误
不是知道你是否 出现过这样的错误 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): 经过各种度娘,无非就是让你检查三种情况 情况一:mapper.xml没有按照传统的maven架构进行放置 情况二:mybatis的配置信…...

NLP 文本分类任务核心梳理
解决思路 分解为多个独立二分类任务将多标签分类转化为多分类问题更换 loss 直接由模型进行多标签分类 数据稀疏问题 标注更多数据,核心解决方案: 自己构造训练样本 数据增强,如使用 chatGPT 来构造数据更换模型 减少数据需求增加规则弥补…...

k8s中pod的创建过程和阶段状态
管理k8s集群 kubectl k8s中有两种用户 一种是登录的 一种是/sbin/nologin linux可以用密码登录,也可以用证书登录 k8s只能用证书登录 谁拿到这个证书,谁就可以管理集群 在k8s中,所有节点都被网络组件calico设置了路由和通信 所以pod的ip是可以…...

NSSCTF刷题篇1
js类型 [SWPUCTF 2022 新生赛]js_sign 这是一道js信息泄露的题目直接查看源码,有一个main.js文件点击之后,有一串数字和一段base64编码,解开base64编码得到这个编码为敲击码 解码在线网站:Tap Code - 许愿星 (wishingstarmoye.…...