Go语言并发编程及依赖管理

news2024/11/29 7:59:23

目录

    • 🧡并发编程
      • Goroutine
      • CSP(Communicating Sequential Processes)
    • 🧡依赖管理
      • 依赖演变
      • 依赖管理三要素

💟这里是CS大白话专场,让枯燥的学习变得有趣!
💟没有对象不要怕,我们new一个出来,每天对ta说不尽情话!
💟好记性不如烂键盘,自己总结不如收藏别人!

🧡并发编程

Goroutine

💌 为什么 Go 语言运行效率如此之高呢?因为它可以充分发挥多核优势,这里有个重要的概念:Goroutine(协程),Go 语言是利用协程达到高并发效果的。

image.png

  • 进程:程序一次动态执行的过程,操作系统资源分配最小单位,有独立内存空间。
  • 线程:轻量级进程,CPU调度的最小单位,多个线程共享所属进程的资源,MB级别。
  • 协程:轻量级线程,由用户控制调度,KB级别。

💌 如何开启一个协程呢?我们只需要在调用的函数前面添加 go 关键字,就能使这个函数以协程的方式运行。

package main

import (
   "fmt"
   "time"
)

func hello(i int) {
   println("hello goroutine:" + fmt.Sprint(i))
}

func main() {
   for i := 0; i < 5; i++ {
      go hello(i) // go + 调用函数名(参数)
   }
   time.Sleep(time.Second) // 阻塞,保证子协程执行完之前主线程不退出
}

可以看到打印结果是并发乱序输出的:

image.png

CSP(Communicating Sequential Processes)

💌 Go 语言中协程之间的通信提倡通过通信共享内存,而非通过共享内存实现通信,二者都支持实现,但是听起来很容易混淆,通过画图可以直观演示:

image.png

🍠 通过通信共享内存:通过通道给目标协程发送信息。Channel(通道)分为无缓冲通道和有缓冲通道,构造方式:

  • 无缓冲通道:make(chan int)
  • 有缓冲通道:make(chan int,2)

image.png

如下代码所示,构造生产者A和消费者B可以实现有缓冲通道的协程通信,生产者产生数字,消费者计算数字的平方,并顺序打印。

package main

func CalSquare() {
   src := make(chan int)     // 生产者
   dest := make(chan int, 3) // 消费者,带缓冲区
   go func() {               // A协程发送0~9至src中
      defer close(src) // defer表示延迟到函数结束时执行,用于释放已分配的资源
      for i := 0; i < 10; i++ {
         src <- i
      }
   }()
   go func() { // B协程计算src中数据的平方,并发送至dest中
      defer close(dest)
      for i := range src {
         dest <- i * i
      }
   }()
   for i := range dest {
      println(i)
   }
}

func main() {
   CalSquare()
}

🍠 通过共享内存通信:需要通过 sync 包中的 lock 进行加锁,如果不加锁会出现问题。如下代码开启5个协程,每个协程进行2000次+1操作,正确结果应该是10000,不加锁的结果不准确。项目中应避免对共享内存进行非并发安全的读写操作。

package main

import (
   "sync"
   "time"
)

var (
   x    int64
   lock sync.Mutex
)

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

func addWithoutLock() { // 不使用锁
   for i := 0; i < 2000; i++ {
      x += 1
   }
}

func Add() {
   x = 0
   for i := 0; i < 5; i++ {
      go addWithoutLock()
   }
   time.Sleep(time.Second)
   println("WithoutLock x =", x)
   x = 0
   for i := 0; i < 5; i++ {
      go addWithLock()
   }
   time.Sleep(time.Second)
   println("WithLock x =", x)
}

func main() {
   Add()
}

image.png

💌 sync 包中的 WaitGruop 也可以实现并发任务同步,Add(delta int) 开启 delta 个协程,Done() 结束协程,Wait() 阻塞主线程。

image.png

🧡依赖管理

依赖演变

💌 Go 依赖主要经历了 GOPATH -> Go Vendor -> Go Module 演变,现在主要采用 Go Module 方式。不同环境(项目)依赖的版本不同,需要控制依赖库的版本。

  • GOPATH:环境变量,Go 语言的工作区,通过 go get 下载最新版本的包到 src 目录下,项目代码直接依赖 src 下的所有源代码。但是有一个弊端就是无法实现package的多版本控制,A、B 项目可能依赖同一个包的不同版本。
  • Go Vendor:在项目目录下新增 vendor 文件夹,所有依赖包副本形式放在其中,通过 vendor => GOPATH 的方式寻址。但是还有问题就是更新项目时可能出现依赖冲突,依然无法控制依赖的版本。
  • Go Module:通过 go.mod 文件管理依赖包版本,通过 go get/go mod 指令工具管理依赖包。既能定义版本规则,又能管理项目依赖关系。

依赖管理三要素

🍠 配置依赖 go.mode

module example/project/app //依赖管理基本单元

go 1.16  //原生库版本

require (  
    //单元依赖标识语法:[Module Path][Version/Pseudo-version]
    example/lib1 v1.0.2
    example/lib2 v1.0.0 // indirect
    example/lib3 v0.1.0-20190725025543-5a5fe074e612
    example/lib4 v0.0.0-20180306012644-bacd9c7ef1dd // indirect
    example/lib5/v3 v3.0.2  // 主版本2+的模块会在路径后增加/vN后缀
    example/lib6 v3.2.0+incompatible  // 对于没有go.mod文件且主版本2+的依赖+incompatible
)

go.mode 定义了自己的版本规则,分为语义版本和基于commit伪版本。

  • 语义版本:${MAJOR}.${MINOR}.${PATCH}

    v版本.新增功能.修复bug,不同版本不兼容,功能向下兼容。

  • 基于commit伪版本:${vx.0.0-yyyymmddhhmmss-abcdefgh1234}

    v版本-时间戳-校验码。

🍠 中心仓库管理依赖库 Proxy

对于 go.mod 中定义的依赖,可以从对应仓库(Github)中下载指定软件依赖,从而完成依赖分发,但是会产生如下问题:

  • 无法保证构建确定性:软件作者直接修改软件版本,导致下次构建使用其他版本的依赖,或者找不到依赖版本。
  • 无法保证依赖可用性:软件作者删除软件,导致依赖不可用。
  • 增加第三方压力:代码托管平台负载过大。

可以使用 Go Proxy 解决上述问题,它会缓存源站中的软件内容,缓存的软件版本不会改变,并且在源站软件删除之后依然可用,构建时会直接从 Go Proxy 站点拉取依赖。Go Modules通过 GOPROXY 环境变量控制依赖寻址顺序:如 proxy1 -> proxy2 -> 源站

GOPROXY="https://proxy1.cn, https://proxy2.cn,direct"

🍠 本地工具 go get/mod

image.png
image.png

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

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

相关文章

Linux (open、write、read、close、lseek、chmod、sync)操作文件的函数详解

目录 一、文件操作方式 二、Linux底层文件操作 1. open 2. write 3. read 4. close 5. lseek 6. chmod 7. sync、syncfs、fsync、fdatasync 三、 Linux 系统调用 四、总结 linux中&#xff0c;一切皆文件&#xff08;网络设备除外&#xff09; 硬件设备也“是”文件&a…

力扣刷题记录——507.完美数、509. 斐波那契数、520. 检测大写字母

本专栏主要记录力扣的刷题记录&#xff0c;备战蓝桥杯&#xff0c;供复盘和优化算法使用&#xff0c;也希望给大家带来帮助&#xff0c;博主是算法小白&#xff0c;希望各位大佬不要见笑&#xff0c;今天要分享的是——《507.完美数、509. 斐波那契数、520. 检测大写字母》。 目…

InfluxDB + Grafana计算成功率

文章目录方式一 借助Grafana的Transfrom方式二 Influx子查询Transfrom介绍建议针对每类Metric&#xff0c;使用一个Metric&#xff0c;增加success的tag区分成功还是失败。 方式一 借助Grafana的Transfrom 第一步&#xff1a;新建2个Query Query Total: SELECT sum("coun…

安科瑞电气火灾监控系统在春晓161#地块人防工程的设计与应用

安科瑞 华楠摘要&#xff1a;本文简述了电气火灾监控系统的组成原理&#xff0c;分析了电气火灾监控系统在应用中的设计依据和相关规范。通过安科瑞剩余电流式电气火灾监控系统在春晓161#地块人防工程电气火灾监控系统项目的实例介绍&#xff0c;阐述了电气火灾监控系统功能的实…

c语言实现扫雷(详细讲解)

本篇介绍,讲解如何使用c语言实现扫雷小游戏. 金句分享: ✨✨✨爱你所爱,行你所行✨✨✨ 目录前言:一、游戏设计思路介绍:效果展示二、游戏的分步讲解2.1、主函数测试区&#xff08;test.c&#xff09;基本构成2.2、游戏中函数实现区(game.c) (重点)2.21、雷盘的创建与初始化函…

centos8 Ambari-2.7.6.3+HDP-3.3.1离线安装详细教程(附安装包)

自2021年1月31日开始,所有Cloudera软件都需要有效的订阅,且订阅费昂贵。此外,CDH6和HDP3将是CDH和HDP的最后企业版本,原有企业版用户无法继续获取新的功能和性能提升。至2022年3月份,CDH/HDP全部停止服务(EoS),用户没办法获取售后支持。由于生产环境系统升级到centos8,…

linux 中 PCIE 中断映射机制

PCIE 中断映射机制 1、 PCIE 中有三种中断方式&#xff0c; MSI&#xff0c;MSI-X 和INTx PCIe总线继承了PCI总线的所有中断特性&#xff08;包括INTx和MSI/MSI-X&#xff09;&#xff0c;以兼容早期的一些PCI应用层软件。 PCI总线最早采用的中断机制是INTx&#xff0c;这是…

基于Flink+kafka实时告警

引出问题 项目使用告警系统的逻辑是将实时数据保存到本地数据库再使用定时任务做判断&#xff0c;然后产生告警数据。这种方式存在告警的延时实在是太高了。数据从产生到保存&#xff0c;从保存到判断都会存在时间差&#xff0c;按照保存数据定时5分钟一次&#xff0c;定时任务…

智慧水务能效管理平台在污水处理厂电气节能中的应用

摘要&#xff1a;污水处理属于高能耗行业&#xff0c;会消耗大量的电能、燃料和药剂等&#xff0c;高能耗不仅会提升污水处理成本&#xff0c;还会加剧能源危机。所以&#xff0c;本文首先探究了污水处理厂耗能的原因&#xff0c;分析了污水处理与节能降耗的关系&#xff0c;然…

MyBatis-Plus数据安全保护(加密解密)

项目创建POM依赖 <dependency><!--MyBatis-Plus 企业级模块--><groupId>com.baomidou</groupId><artifactId>mybatis-mate-starter</artifactId><version>1.2.8</version> </dependency> <!-- https://mvnrepository…

git commit 命令详解

文章目录前言1. git commit 介绍2. git commit 使用3. git commit -m4. git commit -am5. git commit --amend6. commit 多行提交信息7. commit 背后到底发生了什么前言 CSDN 只用来做博客主站文章的转载 博客主站&#xff1a;https://www.itqaq.com 下面地址路径可能会发生变…

Java---中间件---Redis的常见命令和客户端使用

Redis的常见命令和客户端使用1.初识Redis1.1.认识NoSQL1.1.1.结构化与非结构化1.1.2.关联和非关联1.1.3.查询方式1.1.4.事务1.1.5.总结1.2.认识Redis1.3.安装Redis1.3.1.依赖库1.3.2.上传安装包并解压1.3.3.启动1.3.4.默认启动1.3.5.指定配置启动1.3.6.开机自启1.4.Redis桌面客…

VulnHub2018_DeRPnStiNK靶机总结

VulnHub2018_DeRPnStiNK靶机渗透总结 靶机下载地址: https://download.vulnhub.com/derpnstink/VulnHub2018_DeRPnStiNK.ova https://www.dropbox.com/s/8jqor3tuc3jhe1w/VulnHub2018_DeRPnStiNK.ova?dl0 打开靶机,使用nmap扫描出靶机的ip和开放的所有端口 可以看到,靶机开放…

从零开始学习Linux

Linux Linux内核版本&#xff1a;Linux内核运维开发小组&#xff0c;源码在不开源 Linux发行版本&#xff1a;由各大互联网/软件公司定制&#xff0c;开源 一个内核版本是有多种多样的发行版本 Ubuntu&#xff1a;以强大的桌面应用为主&#xff0c;吸收不少Windows用户&…

Docker部署jeecgboot微服务使用记录

docker安装和基础命令 docker安装 docker安装详细步骤 Docker命令 #进入容器 sudo docker exec -it 775c7c9ee1e1 /bin/bash # docker中 启动所有的容器命令 docker start $(docker ps -a | awk { print $1} | tail -n 2) # docker中 关闭所有的容器命令 docker stop $(doc…

(黑马C++)L09 C++类型转换 异常 输入输出流

一、C类型转换 类型转换&#xff08;cast&#xff09;是将一种数据类型转换成另一种数据类型&#xff0c;一般情况下要尽量少的去使用类型转换&#xff0c;除非解决非常特殊的问题。 &#xff08;1&#xff09;静态转换&#xff08;static_cast&#xff09; static_cast使用…

联合证券|内外利好共振 今年A股可更乐观一点

在经历了开年首周的快速拉升后&#xff0c;上星期A股商场全体高位盘整。职业板块从普涨转为快速轮动&#xff0c;前期领涨的新能源及大消费主线均出现了必定程度的回撤&#xff0c;由金融、信创板块接力“领跑”。 展望后市&#xff0c;指数在盘整后能否持续上攻&#xff1f;外…

解决前后端分离Vue项目部署到服务器后出现的302重定向问题

解决前后端分离Vue项目部署到服务器后出现的302重定向问题问题描述问题原因定位问题解决方案校验修改效果相关阅读写在最后问题描述 最近发现自己开发的vue前后端分离项目因为使用了spring security 安全框架&#xff0c;即使在登录认证成功之后再调用一些正常的接口总是会莫名…

Xilinx 7系列FPGA之Spartan-7产品简介

以最低的成本获得无与伦比的性能和功耗效率如果您对功耗或性能的要求与成本要求一样严苛&#xff0c;那么请使用 Spartan -7 FPGA。该系列采用 TSMC&#xff08;台积电&#xff09; 的 28nm HPL 工艺制造&#xff0c;将小尺寸架构的Xilinx 7 系列FPGA 的广泛功能和符合 RoHS 标…

结构体专题详解

目录 &#x1f94e;什么是结构体&#xff1f; ⚾结构体的声明 &#x1f3c0;简单结构体的声明 &#x1f3d0;结构体的特殊声明 &#x1f3c8;结构体嵌套问题 &#x1f3c9;结构体的自引用 &#x1f3b3;结构体的内存大小 &#x1f94c;结构体的内存对齐 ⛳内存对齐的优点 ⚽还…