- Go并发编程
- 依赖管理
- 测试
1.并发编程
Goroutine
使用go 关键词就可以开启一个新的协程去执行另一部分代码
- 协程是用户态的,线程是内核态的,线程可以为多个协程服务
- 提倡通过通信共享内存而不是通过共享内存实现通信
Channel(通道)
channel可以很好的实现多个协程之间通信,从而达到通过通信共享内存的目的 channel是引用类型,用make创建 make(chan 元素类型 , [缓冲区大小])
- 无缓冲的channel需要有人接收了数据才能再发送数据,所以也被称为同步channel
并发安全Lock
当多个协程对同一个变量进行大量操作时,可能会出现结果与预期不符的情况,这时候需要在操作的时候对变量加锁,防止此时被其他协程篡改
WaitGroup
让当前的协程阻塞,直到所有的协程完成任务
2.依赖管理库
Go依赖管理演进
- 不同环境(项目)依赖的版本不同
- 需要控制依赖的版本
目前应用广泛的主要是Go Module
GOPATH
GOPATH的弊端:无法实现package的多版本控制
Go Vendor
- 项目目录下增加venfor文件夹,所有依赖包的副本形势放在文件夹内
- 依赖寻址方式:vendor=>GOPATH
弊端:更新项目又可能出现依赖冲突,导致编译出错
Go Module
- 通过go.mod文件管理依赖包版本
- 通过go get/ go mod 指令工具管理依赖包
- 终极目标:定义版本规则和惯例项目依赖关系
依赖管理三要素:
- 配置文件,描述依赖 go.mod
- 中心仓库管理依赖库 Proxy
- 本地工具 go get/mod
go get工具:
go mod工具:
3.测试
- 单元测试
- Mock测试
- 基准测试
单元测试
Go单元测试-规则
- 所有测试文件以_test.go结尾
- func TestXxx(* testing.T)
- 初始化逻辑放到TeatMain中
举例
被测试的函数
func Hello(name string) string {
return name
}
测试文件
package main
import "testing"
func TestHello(t *testing.T) {
type args struct {
name string
}
tests := []struct {
name string
args args
want string
}{
{name: "test1", want: "tom", args: args{name: "tom"}},//这是放入测试数据的地方
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Hello(tt.args.name); got != tt.want {
t.Errorf("Hello() = %v, want %v", got, tt.want)
}
})
}
}
覆盖率:希望测试数据尽可能覆盖更多的代码行数,提高可信度
Mock
外部依赖 =>稳定&幂等
快速Mock函数,使得测试函数不需要依赖外界的易丢失的数据
- 为一个函数打桩
- 为一个方法打桩
基准测试
- 优化代码,需要对当前代码进行分析
- 内置的测试框架提供了基准测试的能力