这是我参与「第五届青训营 」伴学笔记创作活动的第 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
)