Golang进阶
这是我参与「第五届青训营 」伴学笔记创作活动的第 二 天
1.1 Goroutine
- 协程与线程的区别
- 协程:用户态,轻量级线程,栈KB级别。
- 线程:内核态,一个线程可以跑多个协程,栈MB级别。
- 使用go关键字创建一个goroutine
- 示例
func main() { go func() {} }
1.2 channel
- 创建一个channel make(chan 元素类型,缓冲大小)
- 无缓冲管道:make(chan 元素类型)
- 有缓冲管道:make(chan 元素类型,整数值)
package concurrence
func CalSquare() {
src := make(chan int)
dest := make(chan int, 3)
go func() {
defer close(src)
for i := 0; i < 10; i++ {
src <- i
}
}()
go func() {
defer close(dest)
for i := range src {
dest <- i * i
}
}()
for i := range dest {
println(i)
}
}
1.3 并发安全Lock
- 锁的作用:保护临界区代码执行的原子性,保证并发安全。
- golang中的锁:读写锁和互斥锁
- 死锁示例:
package main import ( "fmt" "sync" "time" ) var l sync.RWMutex func main() { go readAndRead() time.Sleep(1 * time.Second) l.Lock() fmt.Println("----------------- got lock") l.Unlock() time.Sleep(5 * time.Second) } func readAndRead() { l.RLock() fmt.Println("----------------- got rlock") time.Sleep(10 * time.Second) fmt.Println("----------------- 10s passed") l.RLock() fmt.Println("----------------- got 2nd rlock") l.RUnlock() l.RUnlock() } /* shell 执行 `go run main.go` 的结果为: ----------------- got rlock ----------------- 10s passed fatal error: all goroutines are asleep - deadlock! ... */
依赖管理
2.1 golang依赖管理严禁
- GOPATH
- 环境变量$GOPATH
- 项目代码直接依赖src下的代码
- go get 下载最新版本的包到src目录下
- Go Vendor
- 项目目录下增加vendor文件,所有依赖包副本形式放在$ProjectRoot/vendor
- 依赖寻址方式:vendor => GOPATH
- Go Module
- 通过go.mod文件管理依赖包版本
- 通过go/get/go mod指令工具管理依赖包
2.2 依赖管理三要素
- 配置文件,描述依赖 --go.mod
module xxx 依赖管理基本单元 go 1.1x 原生库 require ( 单元依赖 example/lib1 v1.0.2 ) - 中心仓库管理依赖库 --proxy
- 本地工具 --get/mod
测试
3.1 单元测试
- 单元测试-规则
- 所有测试文件以_test.go结尾
- func TestXXX(*testing.T)
- 初始化逻辑放到TestMain中
- 单元测试-assert
- "github.com/stretchr/testify/assert"
- 单元测试-覆盖率
- 单元测试-依赖
- 单元测试-文件处理
- 单元测试-Mock
- 单元测试-基准测试