这是我参与「第三届青训营 -后端场」笔记创作活动的的第2篇笔记。
协程
golang 推荐协程而不是线程,两者的区别
- 协程:用户态,轻量级线程、栈KB级别
- 线程:内核态、线程跑多个协程,栈MB级别 也算go的一大特点,协程是轻量级用户态线程,与线程的对比:
1.线程只能并发,而协程可以并行。
2.创建一个线程,虚拟机会向os请求创建;创建一个协程,则可以通过编译语言自身来完成。
线程执行sqlB同时另起一个线程执行sqlA,每个线程分别请求数据库服务。大多数情况两个线程只是在等待数据库服务响应,处于阻塞等待状态。
主线程执行sqlB同时主线程创建协程执行sqlA,两者都在主线程上,由主线程统一向数据库发送请求一次。 假设执行sql需要三步,请求(1ms),等待(100ms),获取响应(1ms),
线程需要:1+1+100+1+1 = 104
协程需要:1+100+1 = 102
Channel
golang 基于上面的思想推出的数据通道,通过Channel进行通信从而实现共享内存的效果
其中包括有缓冲通道和无缓冲通道
无缓冲通道就是阻塞通道,有缓冲通道通过缓冲,让发送方不必阻塞等待调用方调用,减少了阻塞次数
WaitGroup
golang 标准库sync包中的提供了任务队列WaitGroup,用于阻塞当前协程,直到等待任务数清零
本质上是一个等待任务的计数器
-
WaitGroup.Add(n int): 添加数字,标识需要等待的任务数
-
WaitGroup.Done(): 调用表示一个被等待的任务已经执行完毕 (看源码,本质就是Add(-1))
-
WaitGroup.Wait(); 调用者会阻塞等待当前WaitGroup中任务数清零再开始下一步操作
依赖管理
go的依赖管理,到1.18版本,已经经历了Go Path、Go Vendor、Go Module三次变更
- go.mod:配置文件。描述依赖
- Proxy:代理镜像地址,存储着中心仓库的副本,如果没有会从中心仓库下
- go get/mod:本地工具,用于获取需要的依赖
go path
golang 提供的配置在环境变量中的属性,项目中的依赖直接下载到该path下中的src文件夹中,弊端在于没有版本的管理概念,如果引用了不同的依赖版本没有办法管理
go vender
golang 后来提供在项目目录下增加vendor文件夹,可以把所有的依赖包以副本的形式放进该文件解决了多个项目引用同一个包出现的各种冲突问题,但是仍然没有解决同一个项目依赖不同版本的问题
Go Module
golang 推出的最新的依赖管理方案,解决了同一个项目引用不同依赖同一个包不同版本的问题也满足了市面上主流依赖管理工具的绝大多数功能,以后学习管理依赖的工具直接使用Go Module即可
测试
单元测试
- 所有测试文件以_test.go结尾
- 参数传* testing.T
- 初始化逻辑放到TestMain中,参数testing.M
测试时需要依赖本地的文件,如果文件被修改和被删除就会fail,我们读取文件函数mock,屏蔽对文件的依赖
mock测试
mock monkey : github.com/bouk/monkey