这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天
01.语言进阶
从并发编程的视角了解Go高性能的本质!
高效能的意思:快!
并发与并行
并发:单核多程序,时间片 并行:多核多程序
Go语言可以充分发挥多核优势(多核程序在多个核cpu运行),高效运行。
Goroutine
线程:用户态,轻量级线程,栈MB级别,靠Go调度器调度
协程:内核态,线程跑多个协程,栈KB级别,内核调度 特点:上下文切换快,不经过os的用户态和内核态切换
利用循环核go func进行快速打印,打印结果因其并发异步而随机输出
CSP
通信共享内存:通过通道完成通信共享内存的通讯
共享内存通信:利用一个共享内存区对各个goroutine进行通讯
最好用通信共享内存,而不是共享内存通信
channle
1 无缓冲区:make(chan int)
接收和发送端同步
2 有缓冲区:make(chan int,2)
缓冲区未满,发送不阻塞;
缓冲区未空,接收不阻塞。
并发安全 Lock
Lock,即sync.Mutex锁 多个协程并发执行一个操作,为了安全需要对该操作互斥执行,但这会损失性能。
waitgroup
并发事务实现同步。
- Add() 计数器加+delta
- Done() 计数器-1
- Wait() 阻塞直到计数器为0
func hello(i int) {
println("hello world : " + fmt.Sprint(i))
}
func ManyGo() {
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func(j int) {
defer wg.Done()
hello(j)
}(i)
}
wg.Wait()
}
使用Wait就不用再主程序中sleep, 因为当计数器为0时,停止阻塞吗,这保证了在主程序退出前,所有协程都能跑完。
总结:
- 协程:通过高效的调度模型实现高并发操作
- 通道:通过通信实现共享内存
- sync相关关键字lock,waitgroup:实现并发安全操作和协程间的同步
依赖管理
背景
- 实际工程会比一般helloworld更复杂,我们不可能基于标准库0~1编码搭建,而更多的关注业务逻辑的实现。
- 其他的涉及框架、日志、driver、以及collection等一系列依赖都会通过sdk的方式引入,这样对依赖包的管理就显得尤为重要
Go依赖管理演进
主要讲局限性:
- gopath: 不能实现package的多版本控制
- govender:无法控制依赖的版本
- gomodule:定义了版本规则和依赖关系(选择使用)
依赖管理三要素
- 配置文件 go.mod
- 中心仓库 goproxy
- 本地工具 go get
Go Module实践
go.mod
一般是 [module_path][version]形式 version一般有两种${MAJOR}.${MINOR}.${PATCH}或是vX.Y.Z-yyyymmddhhmmss-comit
依赖分发
GOPROXY是一个 Go Proxy 站点URL列表,可以使用“direct”表示源站。
整体的依赖寻址路径,会优先从proxy1下载依赖,如果proxy1不存在,后下钻proxy2寻找,如果proxy2,中不存在则会回源到源站直接下载依赖,缓存到proxy站点中
使用方法
- go get参数 @none 删除, @v1.1.2 下载特定版本
- go mod参数 init 初始化, download 下载, tidy 删除不需要的依赖
单元测试
背景
测试一般分为,回归测试一般是QA同学手动通过终端回归一些固定的主流程场景,集成测试是对系统功能维度做测试验证,而单元测试测试开发阶段,开发者对单独的函数、模块做功能验证,层级从上至下,测试成本逐渐减低,而测试覆盖率确逐步上升,所以单元测试的覆盖率一定程度上决定这代码的质量。
- 回归测试
- 集成测试
- 单元测试
单元测试
方法:go test hellowithassert_test.go hello.go
覆盖率
在实际项目中,一般的要求是50%~60%覆盖率,而对于资金型服务,覆盖率可能要求达到80%;我们做单元测试,测试分支xxx,则要求函数体足够小,这样就比较简单的提升覆盖率,也符合函数设计的单一职责。
规则
- 测试文件以
_test.go结尾 - 函数名称
func TestXxxx(t *testing.T) - 初始化逻辑放在
TestMain(t *testing.M)
评估测试
代码覆盖率go test加上--cover
mock测试
通过mock实现不对本地文件的强依赖
基准测试
测试cpu损耗之类
函数名称func BenchmarkXxxx(b *testing.b)
项目
稍微感觉有点难度,不过后面能够理解。
总结
今日学习
- 学习了Go语言的并发编程,依赖管理,测试相关知识。
- 学习了Go语言中的goroutine和channel,以及如何使用它们来实现并发编程。
- 学习了如何使用第三方包管理工具管理项目依赖,
- 学习如何使用Go语言自带的测试工具进行单元测试。
- 学习了如何使用gin框架构建一个简单的Web应用程序。
互勉加油
引用
ppt:Go 语言入门 - 工程实践 .pptx - 飞书云文档 (feishu.cn)