这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
首先补充一个上一章的知识点
之前的例子中我们使用time.sleep来保证完成协程的全部执行,那么就存在时间不能够特别精确的问题,那么就存在资源的浪费问题所以引入sync.WaitGroup来减少资源的浪费同时更好的把握协程的执行。
import (
"fmt"
"sync"
"testing"
)
var (
x int64
//用来控制协程的个数
num sync.WaitGroup
lock sync.Mutex
)
func addWithLock() {
for i := 0; i < 20000; i++ {
lock.Lock()
x += 1
lock.Unlock()
}
num.Done()//每完成一个协程-1
}
func addWithoutLock() {
for i := 0; i < 2000; i++ {
x += 1
}
num.Done()
}
func TestAdd(t *testing.T) {
x = 0
//添加协程的个数,需要完成的个数
num.Add(5)
for i := 0; i < 5; i++ {
go addWithLock()
}
num.Wait()//只有五个协程都执行完成之后才不会堵塞,程序才能继续往下执行
fmt.Printf("这是已经加锁的:%v", x)
x = 0
num.Add(5)
for i := 0; i < 5; i++ {
go addWithoutLock()
}
num.Wait()
fmt.Printf("这是未加锁的:%v", x)
}
4 依赖管理
框架、日志等
GOPATH-->Go Vendor --->Go Module
个人理解:兼容性的一步步增强
依赖管理三要素:
-
配置文件、描述依赖 go.mod
-
中心仓库管理依赖库 Proxy
-
本地工具 go get/mod
其中indirect表明不是直接依赖
当一个项目中依赖了同一个项目的不同版本,最终编译时所用的版本为最低兼容版本,就是版本号最高的(如果依赖有1.3 1.4 1.5三个版本,然后使用了1.3 1.4,那么编译的时候所用的版本为1.4)
5 测试
5.1.1 单元测试-规则
- 所有测试文件以_test.go 结尾
- func TestXxx(*testing.T)
- 初始逻辑放到TestMain中
import (
"os"
"testing"
)
func TestMain(m *testing.M) {
//测试前:数据装载、配置初始化等工作
//跑这个package下所有的单元测试
code := m.Run()
//测试后:释放资源等收尾工作
os.Exit(code)
}
5.1.2 单元测试-覆盖率
如何衡量代码是否经过了足够的测试?
如何评项目的测试水准?
如何评估项目是否达到了高水准测试等级?
引出代码覆盖率这一概念
`go test 文件名 --cover
5.1.3 单元测试-Tips
- 一般覆盖率:50%~60%,较高的覆盖率80%+
- 测试分支相对独立、全面覆盖
- 测试单元颗粒度足够小,函数单一职责
5.1.4 单元测试-Mock
monkey:github.com/bouk/monkey
快速 Mock 函数
- 为一个函数打桩
- 为一个方法打桩
对 ReadFirstLine 打桩测试,不再依赖本地文件
6 基准测试
- 优化代码,需要对当前代码分析
- 内置的测试框架提供了基准测试的能力