这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天
并发编程
goroutine
作为低开销的携程,用户态的goroutine可以被内核态的线程创建出来,体量很小,大小从2KB-2GB,同时内核态的线程就可以对应到GMP模型中的M。
channel
go语言提倡通过通信共享内存而不是通过共享内存实现通信
channel可分为有缓冲通道和无缓冲通道
无缓冲通道在被传入时没有被另一goroutine及时读取会引起panic
并发安全sync.Mutex包
Lock()、Unlock()对临界区资源加锁解锁
WaitGroup
Add()、Done()、Wait()
waitgroup内部维护了一个计时器,每起一个goroutine使计数器+1,执行结束计数器-1;住携程阻塞知道计数器为0
依赖管理
go Vendor
- 项目目录下增加vendor文件,所有依赖包副本形式放在$projectRoot/vendor
- 依赖寻址方式:vendor => GOPATH
通过每个项目引入一份依赖的副本,解决了多个项目需要同一个 package依赖的冲突问题。
感觉和go mod的理念很像?
go mod
通过go.mod文件管理依赖包版本
为项目开启go mod
go mod init projectname
indirect标识该包为间接依赖包
go mod tidy下载项目需要的依赖,删除不需要的依赖
测试
规则
- 所有测试文件以
_test.go结尾 - func TestXxx(*testing.T)
- 初始化逻辑放到TestMain中
func TestMain(m *testing.M) {
//测试前:数据装在、配置初始化等前置工作
code:=m.Run()
//测试后:释放资源等收尾工作
os.Exit(code)
}
基准测试
func BenchmarkSprintf(b *testing.B){
num:=10
b.ResetTimer()
for i:=0;i<b.N;i++{
fmt.Sprintf("%d",num)
}
}
- b.ResetTimer是重置计时器,这样可以避免for循环之前的初始化代码的干扰
➜ go test -bench=. -run=none
BenchmarkSprintf-8 20000000 117 ns/op
PASS
ok flysnow.org/hello 2.474s
- -8代表运行时对应的gomaxprocs
- 20000000代表for次数
- 117 ns/op代表每次会花费117ns