Go语言中的协程与依赖管理 | 青训营笔记

42 阅读2分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天

一、本堂课重点内容:

  • 并发编程
  • 依赖管理

二、详细知识点介绍:

并发编程

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

线程:内核态,线程能跑多个携程,栈MB级别

协程间通信

提倡通过通信共享内存,而不是通过共享内存而实现通信

通过通信共享内存:使用通道解决同步问题

通过共享内存实现通信:开辟一个临界区,需要互斥量对其加锁来保证写同步,影响程序性能

goroutine

在go语言中,每个并发执行单元叫作一个goroutine。

当主函数返回时,所有的goroutine都会被直接打断,除了从主函数退出或者直接终止程序,没有其他方法能够让一个goroutine打断另一个goroutine的执行。

channel

channel是goroutine之间的通信机制,他能够让一个goroutine给另一个goroutine发生信息。

每个channel都有一个特殊的类型,也就是channel可以发送数据的类型。

channel有接收和发送两个操作,接收和发送操作都使用 <- 运算符

当channel关闭后,任何对channel的发送操作都会导致panic异常,而对其进行接收操作则会接收到之前已经成功发送的数据,如果没有数据则会产生一个零值数据

  • channel零值为 nil,相同类型的channel可以使用==运算符进行比较
ch := make(chan int) // 无缓存channel
ch := make(chan int,2) // 缓存大小为3的channel
close(ch) // 关闭一个channel

无缓存channel 亦称为 阻塞channel

一个基于无缓存Channels的发送操作将导致发送者goroutine阻塞,直到另一个goroutine在相同的Channels上执行接收操作。反之亦然。

带缓存的channel

带缓存的channel内部持有一个元素队列,队列的最大容量则为创建的channel时的第二个参数指定的。

如果缓存channel的内部队列是满的,那么发送操作将会阻塞直到另一个goroutine执行接收操作释放空间。

相反,如果channel是空的,则会阻塞直到有新的元素添加到channel中。

lock

首先理解一个概念:数据竞争,即是只要有两个 goroutine 同时访问同一变量,且至少其中的一个是写操作时就会发生数据竞争。

其中一种解决办法是,允许多个 goroutine 去访问变量,但是同一时刻最多只有一个 goroutine 在访问。这种方式称为互斥

在Go语言中的 sync 包的 Mutex 类型支持通过信号量来实现并发的同步。他的Lock方法能够获取到 token,而他的 Unlock 方法则会释放这个token。当执行Lock方法时,会尝试获取一个互斥锁,如果其他的 goroutine 已经获得了这个锁的话,那这个操作则会被阻塞直到别的 goroutine 释放这个锁。

依赖管理

版本变迁: GOPATH -> Go Vendor -> Go Module

依赖管理的目的:控制依赖库的版本

GOPATH

Go语言的环境变量 亦是Go项目的工作区

目录结构:

bin:项目编译生成的二进制文件

pkg:项目编译的中间产物,加速编译

src:项目源码

弊端 :无法实现package的多版本控制

Go Vendor

项目目录下增加vendor文件夹,用以存放依赖包的副本

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

弊端:归根结底还是无法控制依赖版本

Go Module

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

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

依赖管理三要素

类似于 Java 中的 Maven

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

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

3.本地工具 -- go get/mod

关于Version的定义

语义化版本

${MAJOR}.${MINOR}.${PATCH}
MAJOR : 大版本,不同的MAJOR之间是可以不兼容的
MINOR :新增函数,不同版本间需要前后兼容
PATCH :代码bug修复

基于 commit 伪版本

vx.0.0-yyyymmddhhmmss-abcdefg1234
第一部分与语义化版本一致
第二部分为时间戳
第三部分为十二位哈希码前缀

ex :

module go_study // 依赖管理基本单元

go 1.19    // 原生库

// 单元依赖
require (
   gorm.io/driver/mysql v1.4.5
   gorm.io/gorm v1.24.5
)

// indirect : 间接依赖
// incompatible : 可能存在不兼容代码逻辑
require (
   github.com/go-sql-driver/mysql v1.7.0 // indirect
   github.com/jinzhu/inflection v1.0.0 // indirect
   github.com/jinzhu/now v1.1.5 // indirect
)

工具

image-20230209031228174.png

image-20230209021751551.png

三、引用参考: