这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天
进阶与依赖管理
并发和并行
并发:多线程在一个核CPU运行
并行:多线程在多个核CPU运行
协程和线程
优势:天然适合高并发
协程:用户态,轻量级线程,栈MB级别
线程:内核态,线程跑多个协程,栈KB级别
协程实现
在函数前加上go关键字
go func(j int) {
hello(j)
}(i)
CSP
CSP(Communicating Sequential Processes) go的并发模型
提倡通过通信来共享内存,而不是通过共享内存实现通信
Channel
make(chan 元素类型,[缓冲大小])
无缓冲通道 make(chan int)
有缓冲通道 make(chan int, 2)
func CalSquare() {
src := make(chan int)
// 消费者缓冲以解决速率不均衡的问题
dest := make(chan int, 3)
go func() {
// defer关键字为延迟执行
defer close(src)
for i := 0; i < 10; i++ {
src <- i
}
}()
go func() {
defer close(dest)
for i := range src {
dest <- i * i
}
}()
for i := range dest {
println(i)
}
}
并发安全 Lock
应该避免共享内存
WaitGroup
func ManyGoWait() {
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
go func(j int) {
defer wg.Done()
hello(j)
}(i)
}
wg.Wait()
}
GOPATH
bin 项目编译的二进制文件
pkg 项目编译的中间产物,加速编译
src 项目源码
弊端:无法实现多版本控制
GOVendor
通过每个项目引入一份依赖的副本
解决了多个项目需要同一个package依赖的冲突问题
弊端:无法控制依赖的版本,更新项目又可能出现依赖冲突,导致编译错误
GoModule
通过go.mod文件管理依赖包版本
通过go get/go mod指令工具管理依赖包
依赖管理三要素
1、配置文件,描述依赖 go.mod
2、中心仓库管理依赖库 Proxy
3、本地工具 go get/mod
go.mod
依赖管理基本单元、原生库、单元依赖
工具-go mod
init 初始化,创建go.mod文件
download 下载模块到本地缓存
tidy 增加需要的依赖,删除不需要的依赖
测试
测试类型
回归测试:
集成测试:功能
单元测试
覆盖度逐渐提升
单元测试
输入进过单元测试得到输出,并与期望输出进行比对
优点:保证质量,提高效率
规则
所以测试文件以_test.go结尾
func TestXxx(*testing.T)
初始化逻辑放到TestMain中
覆盖率
对测试的评估
覆盖率 = 运行的代码行数/总代码行数
Tips
一般覆盖率:50-60,较高覆盖率80+
测试分支相互独立、全面覆盖
测试单元粒度足够小,函数单一职责
Mock
打桩
替换函数地址