Go语言进阶
并发和并行
并发:多线程程序在一个核的cpu上运行;
并行:多线程程序在多个核的cpu上运行
协程和线程
协程:用户态,轻量级线程,栈的开辟大小为KB级别;
线程:内核态,一个线程可以跑多个协程,栈的开辟大小为MB级别;
协程的调用
调用协程时只需在函数前加上go关键字就可以。
fmt.Println("hello go :", i)
}
func main() {
for i := 0; i < 5; i++ {
go func(j int) {
hello(j)
}(i)
}
time.Sleep(time.Second)
}
协程间的通信
(1)通过通信实现共享内存;(2)通过共享内存实现通信。但提倡通过通信共享内存而不是通过共享内存实现通信。原因是后者会存在资源的竞争,需要使用锁,但这样就会影响程序的性能。
Channel类型
需要通过make关键字进行构造。make(chan 元素类型,[缓冲大小]),通过缓冲大小分为无缓冲通道->make(chan int),有缓冲通道->make(chan int,2)。
并发安全Lock
在通过共享内存实现通信时,不可避免的就是要保证共享内存的数据安全,这里就要通过锁机制来进行保护。
WaitGroup
由于无法确定子协程结束的精确时间,在上述代码中都用到sleep,但这样做并不好,所以就需要WaitGroup。WaitGroup内部维护一个计数器,计数器个数代表运行的协程的个数,从而通过计数器来确定子协程是否还存在。
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
go func(j int){
defer wg.Done()
hello(j)
}(i)
}
wg.Wait()
}
Go依赖管理演进
GOPATH->Go Vendor->Go Module
不同环境依赖不同的版本
GOPATH下有三个文件bin(项目编译的二进制文件)、pkg(项目编译的中间产物,加速编译)、src(项目源码)
Go Vendor在项目目录下增加vendor文件,依赖寻址方式:vendor=>GOPATH
Go Module通过go.mod文件管理依赖包版本,通过go get/go mod指令工具管理依赖包
Go的依赖配置会选择最低的兼容版本,子项目分别依赖v1.3和v1.4,会选择v1.4版本
依赖分发->Proxy->可靠稳定
测试
回归测试、集成测试、单元测试;从左往右覆盖率逐渐变大,成本逐渐降低
单元测试规则:(1)所有的测试文件以_test.go结尾;(2)测试函数->func TestXxx(* testing.T);(3)初始化逻辑放到TestMain中。