Go进阶知识
今天是青训营的第二天,学习了Go的并发相关的特性以及工程的测试等内容,下面是记录
Goroutine
首先是大名鼎鼎的goroutine(在官方中文文档里翻译成go程,乐),goroutine可以理解为轻量级的线程,开销很小,相对于线程并发能力更强,在go中的声明也很方便,只需要 go f(x, y, z)即可。一个小栗子
var arr [100]int
var wg sync.WaitGroup
wg.Add(2)
go func(idx int) {...
}(0)
go func(idx int) {...
}(50)
wg.Wait()
这样可以很快地将数组初始化为0-99(乐),总的来说,通过goroutine可以做到很多有意思的事情
Channel
go的channel也是很强大的一个特性,通过channel可以实现不同线程间的通信以及同步化。
channel也可以选择是否设置缓冲区、如果设置了缓冲区可以一定程度上异步执行。
同时当channel缓冲区已经满了的话,channel的写端将进行阻塞,当channel的缓冲区是空的话,channel的读端将阻塞,同时channel可以不仅仅有一个读写端,可以是一个写端、多个读端。
感觉编写并发代码对功力的要求还是比较高的,不然很容易写出死锁(乐)、或者panic还有注意不要写超出channel的缓冲区,不然会panic
一个例子
for i := 0; i < 2; i = i + 1 {
go func(idx int) {
for im := range ch1 {
fmt.Printf("go %d :%d\n", idx, im)
}
}(i)
}
Lock
我们喜闻乐见的锁,很经典的并发控制方式,锁编写正确可以保证并发的安全性,但是如果不慎很有可能造成比较不太好的bug
waitGroup
waitGroup采用计数的方式,感觉像是信号量,大概就是Add会增加计数,Done会计数减一,Wait会阻塞到计数器为0,这样可以避免goroutine由于函数结束而被迫终止的情况,一个例子如下
var wg sync.WaitGroup
wg.Add(2)
go func(idx int) {
...
}(0)
go func(idx int) {
...
}(50)
wg.Wait()
小结
初步了解了go的并发方式,由于刚开始,感觉了解并不深入,还需要再下功夫
依赖管理
GOPATH
前段时间刚入坑时被这个东西折磨了一段时间,GOPATH的管理方式实际上是很不灵活的,在这种模式下工程的开发路径是固定的,于是自然就被淘汰了。由于本人对c++比较熟悉(习惯随便建文件夹,乐),感觉这种模式很奇怪,很不灵活。
Go Vendor
相对于GOPATH灵活性提高了一些,但还是不够
Go mod
Go mod通过配置文件go.mod描述依赖、代理管理依赖库、本地工具进行操作,用go mod显然舒服了很多 灵活性强了很多。
小结
项目经验并不是很丰富,很多的地方并不能切身体会,但基本的逻辑是清晰的。