工程实践 | 青训营笔记

113 阅读5分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第2篇笔记

并发编程

协程

image-20220517214500090

在go语言中,并发是使用协程来实现的
协程与线程不同,协程是线程模型中1:n的实现,而线程是线程模型中1:1的实现
1:n也就是一个内核线程对应n个用户线程,用户线程的切换调度由用户自己实现

协程的实现

image-20220517214856495

go语言中实现协程的方式很简单,只需要在函数前面加上go关键字就可以开启一个协程来运行

协程的通信

image-20220517215103682

go语言是提倡通过通信来共享内存,而不是通过共享内存进行通信
	左图是通过通道进行通信,通道相当于一个先入先出的队列,保证消息的有序性
	右图是通过访问临界区来进行通信,访问临界区所需要的就是进程间的互斥也就是加锁
	

Channel

image-20220518102724869

image-20220518161336351

go语言中channel是一种消息队列
使用make来创建一个channel并返回指针,如make(chan int) make(chan int, 3)
如果使用无缓冲通道来进行通信,会使两个协程直接同步化,所以无缓冲通道又被称为同步通道
有缓冲通道相当于一个生产消费模型,当通道满的时候就会阻塞生产者,当通道空的时候就会阻塞消费者


协程A通过通道src向协程B发送数据,协程B从src中读取数据再写到dest中
从这里可以看出来,通道与共享内存不同,是线程安全的

带缓冲的通道可以解决生产者消费者模型中,资源生产消费不均衡的问题,消费者速度往往是小于生产者的速度,所以需要一个带缓冲的通道来缓冲过剩的资源

并发安全 LOCK

image-20220518162907830

在go语言中的锁为 sync.Mutex
与java语言中的可重入锁很相似,获取锁是lock.Lock(),释放锁是lock.Unlock()

WaitGroup

image-20220518163215223

image-20220518165313322

go语言的同步器件为 WaitGroup
使用方法与Java中的CountDownLatch类似,但是CountDownLatch只能减少不能增加,使用过后就不能再次使用

go的并发组件使用简单
	当wg.Add(5)时,表示同步组件可以获取5次
	当wg.Done()时,表示同步组件被使用了一次
	当wg.Wait()时,表示同步组件正在等待同步

依赖管理

依赖管理演进

image-20220518165738580

image-20220518165829397

image-20220518165935231

image-20220518170259369

image-20220518170531156

image-20220518170739718

GoPath时期,项目都会存放在src目录下,项目依赖的源码也都会存放在src目录下。但是GoPath在面对多个项目的时候,就无法很好的支持这些依赖了
比如当A项目依赖的源码与B项目依赖的源码不相同时,就会出现问题

Go Vendor是为了解决多版本的问题而出现的,其解决方案是每个项目都会有自己依赖的副本,一般会存放到vendor目录下,当vendor目录不存在的时候再回到GoPath目录寻找
但是当项目文件中依赖了一个源码的不同版本的时候,就又会出现版本依赖问题

Go Module是为了解决以上问题而出现的工具

Go Module

image-20220518170820309

image-20220518170911175

image-20220518171440622

image-20220518172337186

Go Module就相当于Java中的Maven一样,是一个管理版本依赖的软件
go.mod文件就相当于pom.xml文件一样,是配置项目依赖的文件,也跟CMakeLists一样,是管理编译的文件,管理了编译的版本
	在go.mod文件中,依赖的version又两部分组成,一个是语义化版本,一个是基于commit伪版本


依赖分发
Go Proxy相当于一个中央仓库,这个中央仓库缓存了许多源码的版本
拉取请求就会转到Proxy中,当Proxy找不到源码时,就会将请求转到第三方的源上

go文件目录

GOROOT = C:\Go
GOPATH = D:\MyWorks
GOPROXY = https://mirrors.aliyun.com/goproxy,https://goproxy.cn,direct

C:\Go    <<--- GOROOT 指向的位置
	--src                 <<--- Go 语言自带的源代码
	--pkg                 <<--- 编译的中间文件放在此文件夹
	--bin                 <<--- 编译的目标文件放在此文件夹
D:\MyWorks	<<--- GOPATH 指向的位置
	--src                 <<--- 项目源代码放置在此文件夹。!!!警告:一个常犯的错误是把 GOPATH 指向此处!!!
		--HelloWorld      <<--- 我们项目源代码所在的文件夹。!!!警告:一个常犯的错误是把 GOPATH 指向此处!!!
		--vendor          <<--- 第三方开源代码文件夹
			--github.com
				--...
	--pkg                 <<--- 编译的中间文件放在此文件夹,Go编译器自动生成此文件夹
	--bin                 <<--- 编译的目标文件放在此文件夹,Go编译器自动生成此文件夹
	

go常用命令

image-20220518172631318

image-20220518173209613

go get命令为拉取一个项目

go mod为修改go.mod文件,有三种常用用法分别是
go mod init			初始化,创建go.mod文件
go mod download	仅下载模块到本地缓存
go mod tidy			增加需要的依赖,删除不需要的依赖

测试

单元测试

image-20220518202417027

image-20220518211747391

image-20220518211757063

image-20220518211958530

测试分支不重不漏
测试粒度足够小、单一职责


幂等:每次结果一样
稳定:对环境稳定性高

mock测试

image-20220519153557158

不需要依赖特定文件就可以进行测试

基准测试

image-20220519153517807

测试性能