Go语言进阶与依赖管理 | 青训营笔记
这是我参与「第五届青训营」伴学笔记创作活动的第2天
语言进阶
并发编程
并发 vs 并行
并发:
Goroutine
通过go关键字创建
协程:用户态,栈KB级别
线程:内核态,栈MB级别
CSP(Communicating Sequential Processes)
Go线程实现模型MPG
M指的是Machine,一个M直接关联了一个内核线程。由操作系统管理。
P指的是”processor”,代表了M所需的上下文环境,也是处理用户级代码逻辑的处理器。它负责衔接M和G的调度上下文,将等待执行的G与M对接。
G指的是Goroutine,其实本质上也是一种轻量级的线程。包括了调用栈,重要的调度信息,例如channel等。
P的数量由环境变量中的GOMAXPROCS决定,通常来说它是和核心数对应,例如在4Core的服务器上回启动4个线程。G会有很多个,每个P会将Goroutine从一个就绪的队列中做Pop操作,为了减小锁的竞争,通常情况下每个P会负责一个队列。
Go协程实现
通过goroutine和channel实现
channel通make创建,
make(chan 元素类型,[缓冲大小])分为
- 无缓冲通道
make(chan int) - 有缓冲通道
make(chan int,2)
并发安全Lock
var lock sync.Mutex
func addWithLock(){
for i:=0; i < 2000; i++{
lock.Lock()
...
lock.Unlock()
}
}
func addWithoutLock(){
for i:= 0; i < 2000; i++{
...
}
}
依赖管理
GOPATH -> Go Vendor -> Go Module
1.GoPath(无法实现package多版本控制)
bin——编译二进制
pkg——中间产物
src——项目源码
2.GO Vendor(1无法控制依赖版本,2更新后出现依赖冲突)
vendor
3.GO MODULE
通过go.mod文件管理依赖包版本。通过go get/go mod 指令工具管理依赖包。
三要素:配置文件,go.mod;中心仓库管理依赖库,proxy;本地工具 go get/ go mod。
go.mod:
主版本会在模块路径后加/vn后缀
依赖分发:
proxy(稳定可靠)
工具go get go mod(init,download,tidy)
测试
单元测试
- 所有测试文件以_test.go结尾
- func TestXxx(* testing.T)
- 初始化逻辑放到TestMain中
测试覆盖率
使用命令:go test name_test.go name.go -- cover
- 衡量代码经过足够测试
- 评价项目测试水准
- 评估项目达到高水准测试等级
Mock
- 为变量打桩
用
gostub给变量打桩 - 为函数/方法打桩
用
gomonkey.ApplyFunc()给单个函数打桩
用gomonkey.ApplyFunc()给连续多个包函数打桩
基准测试
- 代码优化,需要对当前代码分析
- 内置的测试框架提供了基准测试的能力