当前位置: 首页 > news >正文

go并发学习笔记

包含了go学习笔记,含有channel的基础学习,编写数字的平方,如何成组的合并channel,如何优雅的关闭退出并发协程,通道阻塞情况分析,channel与哪些变成情况,可谓是收藏好文.

文章目录

  • 并发1:channel的基础学习
  • 并发2:编写数字的平方
  • 并发3:组装式编写数字的平方
  • 并发4:如何关闭退出并发协程
  • 并发5:通道阻塞情况
  • 并发5:channel情况汇总

并发1:channel的基础学习

func main() {ch := make(chan int, 2)ch <- 1ch <- 2elem, ok := <-chif ok != true {fmt.Println("channel closed")}fmt.Println(elem)
}

一个从channel里读,一个从channel里写

func main() {syncChan1 := make(chan struct{}, 1)syncChan2 := make(chan struct{}, 2)go func() {<-syncChan1fmt.Println("receive a sync signal and wait a second...[receiver]")time.Sleep(time.Second)for {if elem, ok := <-strChan; ok {fmt.Println("Received:", elem, "[receiver]")} else {break}}fmt.Println("stopped [receiver]")syncChan2 <- struct{}{}}()go func() {for _, elem := range []string{"a", "b", "c", "d"} {strChan <- elemfmt.Println("sent:", elem, "[sender]")if elem == "c" {syncChan1 <- struct{}{} //唤醒接收的go携程,fmt.Println("sent a sync signal:", elem, "[sender]")}}fmt.Println("ait 2 seconds...[sender]")time.Sleep(time.Second * 2)close(strChan)syncChan2 <- struct{}{}}()<-syncChan2<-syncChan2
}

赋值写入

type Counter struct {count int
}var mapChan2 = make(chan map[string]*Counter, 1)func (counter *Counter) String() string {return fmt.Sprintf("counter:%d", counter.count)
}
func main() {syncChan := make(chan struct{}, 2)go func() {for {if elem, ok := <-mapChan2; ok {counter := elem["count"]counter.count++} else {break}}fmt.Println("stopped [receiver]")syncChan <- struct{}{}}()go func() {countMap := map[string]*Counter{"count": &Counter{},}for i := 0; i < 5; i++ {mapChan2 <- countMaptime.Sleep(time.Millisecond)fmt.Printf("The count map::%v [sender]\n", countMap)}close(mapChan2)syncChan <- struct{}{}}()<-syncChan<-syncChan
}

用struct进行通信

func main() {dataChan := make(chan int, 5)syncChan1 := make(chan struct{}, 1)syncChan2 := make(chan struct{}, 2)go func() {<-syncChan1for {if elem, ok := <-dataChan; ok {fmt.Printf("Received:%d [receiver]\n]", elem)} else {break}}fmt.Println("Done [receiver]")syncChan2 <- struct{}{}}()go func() {for i := 0; i < 5; i++ {dataChan <- ifmt.Printf("Sent:%d [sender]\n", i)}close(dataChan)syncChan1 <- struct{}{}syncChan2 <- struct{}{}}()<-syncChan2<-syncChan2
}

用select case进行读取

func main() {chanCap := 5intChan := make(chan int, chanCap)for i := 0; i < chanCap; i++ {select {case intChan <- 1:case intChan <- 2:case intChan <- 3:}}for i := 0; i < chanCap; i++ {fmt.Println(<-intChan)}
}

并发2:编写数字的平方

func producer(nums ...int) <-chan int {out := make(chan int)go func() {defer close(out)for _, n := range nums {out <- n}}()return out
}func square(inCh <-chan int) <-chan int {out := make(chan int)go func() {defer close(out)for n := range inCh {out <- n * n}}()return out}func main() {in := producer(1, 2, 3, 4, 5, 6)out := square(in)for ret := range out {fmt.Println(ret)}fmt.Println("done")
}

并发3:组装式编写数字的平方

func producer(nums ...int) <-chan int {out := make(chan int)go func() {defer close(out)for _, n := range nums {out <- n}}()return out
}func square(inCh <-chan int) <-chan int {out := make(chan int)go func() {defer close(out)for n := range inCh {out <- n * n}}()return out}func merge(cs ...<-chan int) <-chan int {out := make(chan int)var wg sync.WaitGroupcollect := func(in <-chan int) {defer wg.Done()for n := range in {out <- n}}wg.Add(len(cs))for _, c := range cs {go collect(c)}go func() {wg.Wait()close(out)}()return out}
func main() {in := producer(1, 2, 3, 4, 5, 6)c1 := square(in)c2 := square(in)c3 := square(in)for ret := range merge(c1, c2, c3) {fmt.Printf("%3d ", ret)}fmt.Println("\ndone")
}

并发4:如何关闭退出并发协程

文章链接:退出

  • 使用for-range退出
  • 使用,ok退出
  • 使用退出通道退出

并发5:通道阻塞情况

// 场景1
// 通道中无数据,但执行读通道func ReadNoDataFromNoBufCh() {noBufCh := make(chan int)<-noBufCh //通道中没数据,你还读,必然阻塞fmt.Println("read from no buffer channel success")}//场景2
//通道中无数据,向通道中写数据,但无协程读取func WriteNoBufCh() {ch := make(chan int)ch <- 1 //通道中无数据,向通道写数据,但无协程读取fmt.Println("write to no buffer channel success")
}//场景3
//通道的缓存中无数据但执行读通道func ReaNoDataFromBufCh() {noBufCh := make(chan int, 1)<-noBufCh //通道中没数据,你还读,必然阻塞fmt.Println("ReaNoDataFromBufCh")}//场景4
//通道缓存已经占满,向通道写数据,但无协程读func WriteBufChButFull() {ch := make(chan int, 1)ch <- 1ch <- 2 //通道缓存已经占满,向通道写数据,但无协程读fmt.Println("WriteBufChButFull")
}

并发5:channel情况汇总

场景原理用法
需要不断从channel读取数据时该方法,当channel关闭时,for循环自动退出,可以防止读取已经关闭的channelfor x := range ch {}
v,ok := <- ch + select操作判断channel是否关闭ok为true,读到数据,ok为false,没读到数据v,ok := <- ch + select
需要对多个通道进行同时处理,但只处理最先发生的channel时select 可以同时监视多个通道的情况,只处理未阻塞的case,当通道为nil时,对应的case永远为阻塞,无论读写,特殊关注:普通情况下,对nil的通道写操作是要panic的select
如果协程只读或只写双向通道变成单向通道单向通道只能只读或只写
异步有缓冲通道可供多个协程同时处理,在一定程度可提高并发性make(chan int,10)
需要超时控制的操作使用selecttime.After,看操作和定时哪个先返回,处理先完成的,就达到了超时控制的效果case <- time.After()
并不希望在channel的读写上浪费时间是为操作加上超时的扩展,这里的操是channel的读或写case <-time.After()
退出时,显示通道所有协程退出所有读ch协程都会收到close(ch)的信号使用close(ch)关闭所有下游协程
使用channel传递信号,而不是传递数据时没数据需要传递时,传递空struct使用chan struct{} 作为信号channel
使用channel传递结构体数据时channel本质上传递的是数据的拷贝,拷贝的数据越小传输效率越高,传递结构体指针,比传递结构体更高效使用channel传递结构体的指针而非结构体
用来获取结果channel可以用来传递变量,channel自身也是变量,可以传递自己使用channel传递channel

相关文章:

go并发学习笔记

包含了go学习笔记,含有channel的基础学习&#xff0c;编写数字的平方&#xff0c;如何成组的合并channel&#xff0c;如何优雅的关闭退出并发协程&#xff0c;通道阻塞情况分析&#xff0c;channel与哪些变成情况&#xff0c;可谓是收藏好文. 文章目录 并发1&#xff1a;chann…...

DeepSeek V3 源码:从入门到放弃!

从入门到放弃 花了几天时间&#xff0c;看懂了DeepSeek V3 源码的逻辑。源码的逻辑是不难的&#xff0c;但为什么模型结构需要这样设计&#xff0c;为什么参数需要这样设置呢&#xff1f;知其然&#xff0c;但不知其所以然。除了模型结构以外&#xff0c;模型的训练数据、训练…...

关于C++数据类型char的类型是整数的思考

学习数据类型时&#xff0c;整数类型中有一个特殊的类型char&#xff0c;可以使用字符来为其赋&#xff0c;也可以用整数来为其赋值&#xff0c;这是怎么一回事&#xff1f;其实任何类型&#xff0c;在计算机的内存中&#xff0c;在最小的存储单元比特中&#xff0c;内部只有0或…...

手写识别革命:Manus AI如何攻克多语言混合识别难题(二)

一、多语种特征分离&#xff1a;对抗训练与解耦表示 1. 梯度反转层&#xff08;GRL&#xff09;实现语言无关特征提取 class GradientReversalFn(Function):staticmethoddef forward(ctx, x, alpha):ctx.alpha alphareturn x.view_as(x)staticmethoddef backward(ctx, grad_…...

windows:curl: (60) schannel: SEC_E_UNTRUSTED_ROOT (0x80090325)

目录 1. git update-git-for-windows 报错2. 解决方案2.1. 更新 CA 证书库2.2. 使用 SSH 连接&#xff08;推荐&#xff09;2.3 禁用 SSL 验证&#xff08;不推荐&#xff09; 1. git update-git-for-windows 报错 LenovoLAPTOP-EQKBL89E MINGW64 /d/YHProjects/omni-channel-…...

typedef 和 using 有什么区别?

在 C 编程中&#xff0c;类型别名&#xff08;Type Aliases&#xff09;是为已有类型定义新名称的一种机制&#xff0c;能够显著提升代码的可读性和可维护性。C 提供了两种工具来实现这一功能&#xff1a;传统的 typedef 和 C11 引入的 using 关键字。 概念 类型别名本质上是为…...

【Java学习笔记】三、运算符,表达式、分支语句和循环语句

运算符与表达式 算数运算符与算数表达式 加减运算符 操作数&#xff1a;2结合方向&#xff1a;从左到右优先级&#xff1a;4级 乘&#xff08;*&#xff09;、除&#xff08;/)和取余&#xff08;%&#xff09;运算符 操作数&#xff1a;2结合方向&#xff1a;从左到右优先…...

广度优先遍历(BFS):逐层探索的智慧

引言&#xff1a;什么是广度优先遍历&#xff1f; 广度优先遍历&#xff08;BFS&#xff09;是一种用于遍历或搜索树&#xff08;Tree&#xff09;和图&#xff08;Graph&#xff09;结构的算法。其核心思想是逐层访问节点&#xff0c;先访问离起点最近的节点&#xff0c;再逐…...

网络HTTP

HTTP Network Request Library A Retrofit-based HTTP network request encapsulation library that provides simple and easy-to-use API interfaces with complete network request functionality. 基于Retrofit的HTTP网络请求封装库&#xff0c;提供简单易用的API接口和完…...

(七)企业级高性能 WEB 服务 - HTTPS 加密

在当今互联网时代&#xff0c;数据安全成为了每个企业和开发者必须关注的重点。尤其是对于Web服务来说&#xff0c;如何保障用户数据的安全传输是至关重要的。本文将深入探讨HTTPS加密的原理、Nginx的HTTPS配置&#xff0c;以及如何通过Nginx实现高性能的Web服务。 1. HTTPS加密…...

[HTTP协议]应用层协议HTTP从入门到深刻理解并落地部署自己的云服务(2)

标题&#xff1a;[HTTP协议]应用层协议HTTP从入门到深刻理解并落地部署自己的云服务(2) 水墨不写bug 文章目录 一、无法拷贝类(class uncopyable)的设计解释&#xff1a;重要思想&#xff1a;使用示例 二、锁的RAII设计解释重要考虑使用示例 三、基于RAII模式和互斥锁的的日志…...

MySQL(单表)知识点

文章目录 1.数据库的概念2.下载并配置MySQL2.1初始化MySQL的数据2.2注册MYSQL服务2.3启动MYSQL服务2.4修改账户默认密码2.5登录MYSQL2.6卸载MYSQL 3.MYSQL数据模型3.1连接数据库 4.SQL简介4.1SQL的通用语法4.2SQL语句的分类4.3DDL语句4.3.1数据库4.3.2表(创建,查询,修改,删除)4…...

HarmonyOS Next 属性动画和转场动画

HarmonyOS Next 属性动画和转场动画 在鸿蒙应用开发中&#xff0c;动画是提升用户体验的关键要素。通过巧妙运用动画&#xff0c;我们能让应用界面更加生动、交互更加流畅&#xff0c;从而吸引用户的注意力并增强其使用粘性。鸿蒙系统为开发者提供了丰富且强大的动画开发能力&…...

使用Node.js从零搭建DeepSeek本地部署(Express框架、Ollama)

目录 1.安装Node.js和npm2.初始化项目3.安装Ollama4.下载DeepSeek模型5.创建Node.js服务器6.运行服务器7.Web UI对话-Chrome插件-Page Assist 1.安装Node.js和npm 首先确保我们机器上已经安装了Node.js和npm。如果未安装&#xff0c;可以通过以下链接下载并安装适合我们操作系…...

Docker 部署 MongoDB 并持久化数据

Docker 部署 MongoDB 并持久化数据 在现代开发中&#xff0c;MongoDB 作为 NoSQL 数据库广泛应用&#xff0c;而 Docker 则提供了高效的容器化方案。本教程将介绍如何使用 Docker 快速部署 MongoDB&#xff0c;并实现数据持久化&#xff0c;确保数据不会因容器重启或删除而丢失…...

DeepSeek + 沉浸式翻译 打造智能翻译助手

本文详细介绍如何使用 DeepSeek API 沉浸式翻译插件打造个性化翻译助手。 一、DeepSeek API 配置 基础配置 API 基础地址&#xff1a;https://api.deepseek.com需要申请 API Key支持与 OpenAI SDK 兼容的调用方式 可用模型 deepseek-chat&#xff1a;已升级为 DeepSeek-V3&am…...

cdn取消接口缓存

添加cdn后&#xff0c;使用cdn加速域名访问接口 是缓存&#xff0c;不是最新的数据&#xff0c;如果使用局域网则是最新的数据&#xff0c;如果修改配置&#xff0c;确保使用cdn域名请求的接口返回不是缓存 要确保通过CDN加速域名访问接口时返回的是最新的数据&#xff0c;而不…...

字节跳动C++客户端开发实习生内推-抖音基础技术

智能手机爱好者和使用者&#xff0c;追求良好的用户体验&#xff1b; 具有良好的编程习惯&#xff0c;代码结构清晰&#xff0c;命名规范&#xff1b; 熟练掌握数据结构与算法、计算机网络、操作系统、编译原理等课程&#xff1b; 熟练掌握C/C/OC/Swift一种或多种语言&#xff…...

OpenHarmony子系统开发编译构建指导

OpenHarmony子系统开发编译构建指导 概述 OpenHarmony编译子系统是以GN和Ninja构建为基座&#xff0c;对构建和配置粒度进行部件化抽象、对内建模块进行功能增强、对业务模块进行功能扩展的系统&#xff0c;该系统提供以下基本功能&#xff1a; 以部件为最小粒度拼装产品和独…...

MySQL进阶-关联查询优化

采用左外连接 下面开始 EXPLAIN 分析 EXPLAIN SELECT SQL_NO_CACHE * FROM type LEFT JOIN book ON type.card book.card; 结论&#xff1a;type 有All ,代表着全表扫描&#xff0c;效率较差 添加索引优化 ALTER TABLE book ADD INDEX Y ( card); #【被驱动表】&#xff0…...

突破不可导策略的训练难题:零阶优化与强化学习的深度嵌合

强化学习&#xff08;Reinforcement Learning, RL&#xff09;是工业领域智能控制的重要方法。它的基本原理是将最优控制问题建模为马尔可夫决策过程&#xff0c;然后使用强化学习的Actor-Critic机制&#xff08;中文译作“知行互动”机制&#xff09;&#xff0c;逐步迭代求解…...

rknn优化教程(二)

文章目录 1. 前述2. 三方库的封装2.1 xrepo中的库2.2 xrepo之外的库2.2.1 opencv2.2.2 rknnrt2.2.3 spdlog 3. rknn_engine库 1. 前述 OK&#xff0c;开始写第二篇的内容了。这篇博客主要能写一下&#xff1a; 如何给一些三方库按照xmake方式进行封装&#xff0c;供调用如何按…...

CocosCreator 之 JavaScript/TypeScript和Java的相互交互

引擎版本&#xff1a; 3.8.1 语言&#xff1a; JavaScript/TypeScript、C、Java 环境&#xff1a;Window 参考&#xff1a;Java原生反射机制 您好&#xff0c;我是鹤九日&#xff01; 回顾 在上篇文章中&#xff1a;CocosCreator Android项目接入UnityAds 广告SDK。 我们简单讲…...

vue3 定时器-定义全局方法 vue+ts

1.创建ts文件 路径&#xff1a;src/utils/timer.ts 完整代码&#xff1a; import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...

Linux-07 ubuntu 的 chrome 启动不了

文章目录 问题原因解决步骤一、卸载旧版chrome二、重新安装chorme三、启动不了&#xff0c;报错如下四、启动不了&#xff0c;解决如下 总结 问题原因 在应用中可以看到chrome&#xff0c;但是打不开(说明&#xff1a;原来的ubuntu系统出问题了&#xff0c;这个是备用的硬盘&a…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

ABAP设计模式之---“简单设计原则(Simple Design)”

“Simple Design”&#xff08;简单设计&#xff09;是软件开发中的一个重要理念&#xff0c;倡导以最简单的方式实现软件功能&#xff0c;以确保代码清晰易懂、易维护&#xff0c;并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计&#xff0c;遵循“让事情保…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

【Linux】Linux 系统默认的目录及作用说明

博主介绍&#xff1a;✌全网粉丝23W&#xff0c;CSDN博客专家、Java领域优质创作者&#xff0c;掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围&#xff1a;SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...

【前端异常】JavaScript错误处理:分析 Uncaught (in promise) error

在前端开发中&#xff0c;JavaScript 异常是不可避免的。随着现代前端应用越来越多地使用异步操作&#xff08;如 Promise、async/await 等&#xff09;&#xff0c;开发者常常会遇到 Uncaught (in promise) error 错误。这个错误是由于未正确处理 Promise 的拒绝&#xff08;r…...