Go语言进阶和依赖管理(二)——并发和依赖管理

news2024/10/9 2:22:13

文章目录

    • 一、本文重点内容:
    • 二、详细知识点介绍:
      • 1、并发和并行
        • 并发:
        • 并行:
        • 结论:
      • 2、Go的协程
        • 协程:
        • 线程:
      • 3、协程通信
        • 方式一:使用通道交换数据
        • 方式二:使用共享内存完成数据交换
      • 4、协程通道
      • 5、WaitGroup计数器
      • 6、Go的依赖管理演进
        • GOPATH
        • Go Vendor
        • Go Modoule
      • 7、Go依赖配置(go.mod)
        • 版本:
      • 8、工具 go.get/go.mod
    • 三、实践练习例子:
      • 1、协程使用:快速打印协程编号
      • 2、协程通道使用
      • 3、并发安全 Lock
      • 4、语法熟悉——猜谜小游戏
      • 5、语法熟悉——彩云翻译数据爬取
    • 四、课后个人总结:

一、本文重点内容:

  • 本堂课的知识要点有哪些?

    go语言进阶

    1、并发和并行

    2、Go的协程

    3、协程通信

    4、协程通道

    5、WaitGroup计数器

    go的依赖管理

    1、Go的依赖演进

    2、Go依赖配置

    3、工具(go.get/go.mod)

二、详细知识点介绍:

1、并发和并行

并发:

image-20230201174841271

并行:

image-20230201174921569

结论:

go可以充分发挥多核并发的优势,高效运行。

可以说go就是为了并发而生的。

2、Go的协程

image-20230201175435983

协程:

用户态,轻量级线程,栈大小:KB级别。

go语言一次可以创建上万协程。

线程:

内核态,线程上可以运行多个协程,比较消耗资源。

栈大小:MB级别。

3、协程通信

方式一:使用通道交换数据

image-20230201185237664

方式二:使用共享内存完成数据交换

image-20230201185352598

提倡使用通道实现协程通信

4、协程通道

创建方式:make(chan,元素类型,[缓冲大小])

分类:

1、无缓冲通道:同步通道,保证两个协程同步。

2、有缓冲通道:典型生产消费模型。

image-20230201185937088

5、WaitGroup计数器

image-20230201200201472

示例代码:

//go:build ignore
// +build ignore

package main

import "sync"

func main() {
   var wg sync.WaitGroup
   wg.Add(5)
   for i := 0; i < 5; i++ {
      go func(j int) {
         defer wg.Done()
         println(j)
      }(i)
   }
   wg.Wait()
}

运行结果:

image-20230201200800023

6、Go的依赖管理演进

image-20230201200938560

GOPATH

image-20230201201242191

1、项目代码直接依赖src下的代码

2、go get下载最新版本的包到src目录下

弊端:

image-20230201202607326

无法实现pkg的多版本控制

Go Vendor

项目目录下增加vendor文件,所有依赖包副本形式放在$ProjectRoot/vendor

依赖寻址方式: vendor => GOPATH

image-20230201203434320

通过每个项目引入一份依赖的副本,解决了多个项目需要同一个package依赖的冲突问题。

弊端:

image-20230201203626045

问题

无法控制依赖的版本。
更新项目又可能出现依赖冲突,导致编译出错。

Go Modoule

通过go.mod文件管理依赖包版本

通过go get/go mod指令工具管理依赖包

三要素:

1.配置文件,描述依赖:go.mod

2.中心仓库管理依赖库:Proxy

3.本地工具:go get/mod

7、Go依赖配置(go.mod)

image-20230201204024620

版本:

image-20230201204200863 image-20230201204223367

注:

1、主版本2+模块会在模块路径增加/vN后缀。
2、对于没有go.mod文件并且主版本2+的依赖,会+incompatible

8、工具 go.get/go.mod

image-20230201204622420

image-20230201204713423

三、实践练习例子:

1、协程使用:快速打印协程编号

代码:

package main

import (
   "fmt"
   "time"
)

func main() {
   for i := 0; i < 5; i++ {
      go func(j int) {
         holle(j)
      }(i)
   }
   time.Sleep(time.Second)
}
func holle(i int) {
   println("holle goroutine:" + fmt.Sprint(i))
}

运行结果:

image-20230201180758150

可以看到确实是多个协程共同运行

2、协程通道使用

目的:

A子协程发送0~9数字

B子协程计算输入数字的平方

主协程输出最后的平方数

代码:

//go:build ignore
// +build ignore

package main

import "fmt"

func main() {
   // 创建两个通道
   src := make(chan int)
   dest := make(chan int, 2)
   // 协程A
   go func() {
      defer close(src)
      for i := 0; i < 10; i++ {
         src <- i
      }
   }()
   // 协程B
   go func() {
      defer close(dest)
      for i := range src {
         dest <- i * i
      }
   }()
   // 主协程
   for i := range dest {
      fmt.Println(i)
   }
}

运行结果:

image-20230201191144846

3、并发安全 Lock

目的:对变量执行2000次+1操作,5个协程并发执行

代码:

package main

import (
   "sync"
   "time"
)

func main() {
   add()
}

var (
   x    int64
   lock sync.Mutex
)

func addWithLock() {
   for i := 0; i < 2000; i++ {
      lock.Lock()
      x++
      lock.Unlock()
   }
}

func addWithoutLock() {
   for i := 0; i < 2000; i++ {
      x++
   }
}
func add() {
   x = 0
   for i := 0; i < 5; i++ {
      go addWithLock()
   }
   time.Sleep(time.Second)
   println("使用锁:", x)
   x = 0
   for i := 0; i < 5; i++ {
      go addWithoutLock()
   }
   time.Sleep(time.Second)
   println("不使用锁:", x)
}

运行结果:

image-20230201193205915

可以看到使用了锁后,保证了共享变量的数据可见性。

4、语法熟悉——猜谜小游戏

目的:玩家随机猜测一个1~100的数,返回是否正确,不正确返回与目标数的大小关系。

代码:

package main

import (
   "bufio"
   "fmt"
   "math/rand"
   "os"
   "strconv"
   "strings"
   "time"
)

func main() {
   // 生成随机数
   maxNum := 100
   rand.Seed(time.Now().UnixNano())
   secretNum := rand.Intn(maxNum)
   // fmt.Println("最终答案:", secretNum)
   fmt.Println("请输入1~100中随机一个数:")
   count := 0
   for {
      // 输入猜测数
      reader := bufio.NewReader(os.Stdin)
      input, err := reader.ReadString('\n')
      if err != nil {
         fmt.Println("输入错误,请重试!!!")
         count++
         continue
      }
      input = strings.TrimSuffix(input, "\r\n")
      guess, err := strconv.Atoi(input)
      if err != nil {
         fmt.Println("不是整数,请重试!!!", err)
         count++
         continue
      }
      fmt.Println("你的猜测数:", guess)
      if guess < 1 && guess > 100 {
         fmt.Println("数字不在范围内,重新输入:")
         count++
         continue
      }
      // 判断是否正确
      count++
      if guess < secretNum {
         fmt.Println("数字小于答案,请再次尝试")
      } else if guess > secretNum {
         fmt.Println("数字大于答案,请再次尝试")
      } else {
         fmt.Println("恭喜你答对了!!!")
         fmt.Println("一共花费了:", count, "次")
         break
      }
   }

}

测试:

GOROOT=D:\Goland\go1.19.2 #gosetup
GOPATH=C:\Users\lenovo\go #gosetup
D:\Goland\go1.19.2\bin\go.exe build -o C:\Users\lenovo\AppData\Local\Temp\GoLand\___go_build_TestDemo1_go.exe C:\Users\lenovo\go\src\awesomeProject\main\TestDemo1.go #gosetup
C:\Users\lenovo\AppData\Local\Temp\GoLand\___go_build_TestDemo1_go.exe
请输入1~100中随机一个数:
50
你的猜测数: 50
数字大于答案,请再次尝试
25
你的猜测数: 25
数字小于答案,请再次尝试
38
你的猜测数: 38
数字小于答案,请再次尝试
44
你的猜测数: 44
数字大于答案,请再次尝试
41
你的猜测数: 41
数字小于答案,请再次尝试
42
你的猜测数: 42
数字小于答案,请再次尝试
43
你的猜测数: 43
恭喜你答对了!!!
一共花费了: 7 次

进程 已完成,退出代码为 0

5、语法熟悉——彩云翻译数据爬取

目的:输入一个单词,爬取翻译的相关信息

代码:

package main

import (
   "fmt"
   "io/ioutil"
   "log"
   "net/http"
   "strings"
)

type DictRequest struct {
   trans_type string
   source     string
}

func main() {
   client := &http.Client{}
   // 注意,"和`的混合使用
   var data = strings.NewReader(`{"trans_type": "en2zh","source": "good"}`)
   request, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data)
   if err != nil {
      log.Fatal(err)
   }
   request.Header.Set("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36 Edg/107.0.1418.35")
   request.Header.Set("content-type", "application/json;charset=UTF-8")
   request.Header.Set("origin", "https://fanyi.caiyunapp.com")
   request.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi")
   do, err := client.Do(request)
   if err != nil {
      log.Fatal(err)
   }
   defer do.Body.Close()
   text, err := ioutil.ReadAll(do.Body)
   if err != nil {
      log.Fatal(err)
   }
   fmt.Printf("%s\n", text)
}

四、课后个人总结:

这节课熟悉了语法知识,写了很多go的代码。也了解了Go在并发并行方面的知识,Go的依赖管理方面的配置也明白了不少。

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

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

相关文章

SpringBoot 与 SpringCloud 有什么区别?

&#x1f3c6;今日学习目标&#xff1a; &#x1f340;SpringBoot 与 SpringCloud 有什么区别&#xff1f; ✅创作者&#xff1a;林在闪闪发光 ⏰预计时间&#xff1a;30分钟 &#x1f389;个人主页&#xff1a;林在闪闪发光的个人主页 &#x1f341;林在闪闪发光的个人社区&am…

深拷贝,浅拷贝,引用拷贝有什么区别?

目录 引用拷贝 浅拷贝 深拷贝 深拷贝,浅拷贝,引用拷贝有什么区别? 引用拷贝 当我们向复制一个对象的时候,自然想到的就是赋值,直接赋值给另外一个变量,这种做法只是赋值了对象的地址,即两个变量现在指向的是同一个对象,任意一个对象操作这个属性都会影响到另外一个变量,这…

成为一名网络安全工程师,你应该学习什么?

前言 这是我的建议如何成为网络安全工程师&#xff0c;你应该按照下面顺序学习。 简要说明 第一件事你应该学习如何编程&#xff0c;我建议首先学python&#xff0c;然后是java。 &#xff08;非必须&#xff09;接下来学习一些算法和数据结构是很有帮助的&#xff0c;它将帮…

jQuery select三级联动

功能描述&#xff1a; 1 实现三级联动&#xff0c;ajax请求数据。 根据选定级别&#xff0c;查询该级别下的项目类别&#xff1b;根据选择类别&#xff0c;查询该级别类别下所属项目列表&#xff1b; 前端涉及知识点&#xff1a; &#xff08;1&#xff09;(‘#app’).change…

【云原生kubernetes】k8s控制器Deployment使用详解

前言 在上一篇我们聊了k8s中各种控制器的使用&#xff0c;本篇将以控制器中比较常用的一种控制器Deployment 进行详细的说明。 一、Deployment 简介 为了更好解决服务编排的问题&#xff0c;kubernetes在V1.2版本开始&#xff0c;引入了Deployment控制器&#xff1b; 需要说明…

47 转置卷积【动手学深度学习v2】】

47 转置卷积【动手学深度学习v2】】 深度学习学习笔记 学习视频&#xff1a;https://www.bilibili.com/video/BV17o4y1X7Jn/?spm_id_from333.1007.top_right_bar_window_history.content.click&vd_source75dce036dc8244310435eaf03de4e330 转置卷积 卷积不会增大输入的高…

【Python小游戏】99%的人都不知道,“猜数字”游戏这么玩才能快速胜出,少年,要不要来猜猜看啊~(附源码)

前言 日子从不亏欠&#xff0c;每一个努力向上的人&#xff0c; 未来的走运, 都是过往尽力的积累。 人勤春来早&#xff0c;奋进正当时。新春伊始&#xff0c;我们迎来了2023年开工第一天。 栗子同学恭祝大家开工大吉&#xff0c;新年新气象&#xff0c;万事开门红&#xff…

Spring事务案例:模拟银行转账

Spring事务案例&#xff1a;模拟银行转账一. 概念二. 原程序2.1 表&#xff1a;2.2 service层接口&#xff1a;2.3 dao层接口&#xff1a;2.4 service实现类&#xff1a;2.5 测试用例&#xff1a;三.使用事务改进3.1 开启注解式事务驱动&#xff1a;3.2 开启事务&#xff1a;3.…

python使用pptx库-从一个ppt复制页面到另一个ppt里面

python使用pptx库-从一个ppt复制页面到另一个ppt里面 作者&#xff1a;虚坏叔叔 博客&#xff1a;https://xuhss.com 早餐店不会开到晚上&#xff0c;想吃的人早就来了&#xff01;&#x1f604; 一、原理 如题&#xff0c;我有一个模板课件.pptx&#xff1a; 其内容&#xf…

百趣代谢组学文献分享:大麦盐胁迫响应机制的组学分析

前言 百趣代谢组学文献分享&#xff0c;我国受盐碱化危害耕地面积超过1.4亿亩&#xff0c;严重危险粮食安全和三农问题的解决。因此开发耐盐农作物并研究其耐盐机制具有迫在眉睫的重要意义。 代谢组学文献分享&#xff0c;浙江大学吴德志教授研究组最近发表的研究成果比较了耐…

Jmeter之界面语言设置

一、临时性设置中文 临时性设置&#xff1a;设置后只对本次使用有效&#xff0c;重启Jmeter后恢复默认语言。 选择Options—>Choose Language—>选择其他语言&#xff08;例如&#xff1a;Chinese&#xff08;Simplified&#xff09;简体中文&#xff09;设置成功。重启…

32 基变换和图像压缩

一、知识概要 本节主题是线性变换与矩阵的关联&#xff0c;从图像压缩与信号处理的应用引入&#xff0c;介绍几种方便的基向量&#xff1a;傅里叶&#xff0c;小波。最后从代数角度大体上介绍了基变换与变换矩阵的关系。 二、图像处理 首先我们假设有一个 512 * 512 的黑白图…

StarRocks斩获「2022 掘金引力榜」年度技术品牌传播案例 Top 10!

近日&#xff0c;由稀土掘金技术社区打造的「掘金引力榜」正式公布&#xff0c;由StarRocks社区举办的StarRocks Summit Asia 2022荣获「掘金引力榜 2022 年度技术品牌传播案例 Top10」&#xff01;掘金是面向全球中文开发者的技术社区。「掘金引力榜」是由稀土掘金技术社区打造…

【MyBatis持久层框架】配置文件实现增删改查实战案例(下)

前言 前面我们学习了 MyBatis 持久层框架的原生开发方式和 Mapper 代理开发两种方式&#xff0c;解决了使用 JDBC 基础性代码操作数据库时存在的硬编码和操作繁琐的问题。 在配置文件实现增删改查上篇中&#xff0c;我们详细讲解了常用的查询操作&#xff0c;例如查询所有数据…

Spring Boot 项目 - API 文档搜索引擎

在线体验 : http://43.139.1.94:9090/index.html项目 Gitee 链接 : API 文档搜索引擎1.认识搜索引擎我们平时查百度, 搜狗的时候, 结果页会显示若干条相关结果 , 每个结果几乎都包含图片, 标题, 描述, 展示 URL以及时间等等.1.1 搜索引擎的本质输入一个查询词, 得到若干个结果,…

stm32学习笔记-1 STM32简介

1 STM32简介 [toc] 注&#xff1a;笔记主要参考 江科大自化协 教学视频“STM32入门教程-2023持续更新中”。 注&#xff1a;工程及代码文件放在了本人的Github仓库。 1.1 套件简介 本教程使用STM32最小系统板&#xff08;STM32F103C8T6&#xff09;面包板硬件平台进行学习。…

微信小程序 Springboot校园自动点餐系统带跑腿 java

开发语言&#xff1a;Java 小程序前端框架&#xff1a;uniapp 小程序运行软件&#xff1a;微信开发者 可选运行软件:webapp (hbuiderx) 前端开发语言:vue.js 后端技术:Springboot(SpringSpringMVCMyBatis) 可选技术:springboot 后端开发环境:idea和eclipse都支持 数据库:mysql …

六、服务端开发

服务器端开发&#xff1a;服务器设计框架&#xff1a;缓解和转发的作用连接音箱和app最大一个作用转发一个app操作音箱app绑定音箱服务器类实现&#xff1a;jsoncpplibventverser.h#ifndef SERVER_H #define SERVER_H#include <event.h>#define IP "172.17.7.99&…

【C++入门】缺省参数

目  录1 缺省参数1.1 缺省参数概念1.2 缺省参数分类1.3 缺省参数使用注意1 缺省参数 1.1 缺省参数概念 缺省参数是声明或定义函数时为函数的参数指定一个缺省值。 在调用该函数时&#xff0c;如果没有指定实参&#xff0c;则采用该形参的缺省值&#xff0c;否则使用指定的实…

Spring Profiles 实现多环境配置 ,切换环境

Spring Profiles 实现多环境配置 Spring Profiles 就是针对应用程序&#xff0c;不同环境需要不同配置加载的一种解决方案。 使用场景: 我们平常项目开发&#xff0c;经常需要根据不同的环境进行配置的修改&#xff0c;比如在本地开发会加载本机的配置和开发环境数据库&#x…