这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天
并发
协程可以看作轻量级的线程。
Goroutine
go在创建协程只需要在调用函数时在函数前加go
func hello(i int){
*******
}
func HelloGoroutine(){
for ; ; {
go func(j int){
hello(j)
}(i)
}
}
WaitGroup ,信道(channel),lock
常见的 3 种并发控制的方式
channel分为有缓存通道和无缓存通道make(chan,[缓存大小])
lock对协程临界区加一层保护,提供一个缓冲区保证程序在并行的时候不会出错。
lock.lock()
*****
lock.unlock()
如果并发启动了多个子协程,需要等待所有的子协程完成任务,WaitGroup 非常适合于这类场景wg.Wait() 会等待所有的子协程任务全部完成,所有子协程结束后,才会执行 wg.Wait() 后面的代码。waitGroup提供三种方法对协程进行控制。
- add(delta int ) 计数器加上delta的值
- Done() 计数器减一
- Wait() 阻塞直到计数器为0 WaitGroup 只能等待子协程结束,但是并不能主动通知子协程退出。
测试
单元测试
单元测试是一个优秀项目不可或缺的一部分,特别是在一些频繁变动和多人合作开发的项目中尤为重要。
规则
- 测试文件以
_test.go结尾 - func TestXxxx(t *Testing.T)
- 初始化逻辑放在TestMain中
go test -v,-v参数会显示每个用例的测试结果,另外-cover参数可以查看覆盖率。一般覆盖率在50-60,高效覆盖率在80+。
Benchmark 基准测试
基准测试用例的定义如下:
func BenchmarkName(b *testing.B){
// ...
}
```
1. 函数名必须以 `Benchmark` 开头,后面一般跟待测试的函数名
2. 参数为 `b *testing.B`。
3. 执行基准测试时,需要添加 `-bench` 参数。
基准测试报告每一列值对应的含义:
```
type BenchmarkResult struct {
N int // 迭代次数
T time.Duration // 基准测试花费的时间
Bytes int64 // 一次迭代处理的字节数
MemAllocs uint64 // 总的分配内存的次数
MemBytes uint64 // 总的分配内存的字节数
}
```