这是我参与「第五届青训营 」笔记创作活动的第2天
并发编程
在Go语言中,每一个并发的执行单元叫作一个goroutine。
goroutine类似于线程,但其栈较小,一般是2kB
Go关键字 :go
当一个程序启动时,其主函数即在一个单独的goroutine中运行,我们叫它main goroutine。新的goroutine会用go语句来创建。
go f()
channel
如果说goroutine是Go语言程序的并发体的话,那么channels则是它们之间的通信机制。一个channel是一个通信机制,它可以让一个goroutine通过它给另一个goroutine发送值信息。每个channel都有一个特殊的类型,也就是channels可发送数据的类型。
一个可以发送int类型数据的channel一般写为chan int
ch:=make(chan int)
channel 发送与接受
ch <- x 向ch发送
x=<-ch 从ch中取出
创建有缓存的channel
make(chan int,3)
一把大🔒保平安
lock sync.Mutex
lock.Lock()
x+=1
lock.Lock()
现象解释:
并发带来的问题:回忆一条指令的执行过程:
取出变量的值,对变量值进行修改,将值存回变量 将变量X进行累加时,从内存中取值到寄存器中,在寄存器中完成累加后,写回;并发时,一个线程将变量取出,还没来得及将更新后的变量写回,另一个线程这时候又去取变量,造成变量只加了一次
依赖管理
实际开发过程中,除了系统库,代码可能会引用来自网络和第三方的依赖库,这些依赖库来自不同站点的不同存储库,拥有不同的版本。为使得管理更清晰方便,Go引入了依赖管理。
其他语言依赖管理:Java 的 Maven/Gradle,.NET 的 NuGet,Python 的pip,Rust 的 Cargo,JavaScript(NodeJS)的 npm/yarn/pnpm
依赖管理的演进
Go path
公共环境变量,无版本冲突控制方法
Go vender
在项目文件夹下新建一个vender文件夹,存放依赖库的副本
Go Module
通过 go.mod文件声明所需的依赖和版本;通过 go mod / go get 命令管理依赖
单元测试
测试的意义
项目部署之前进行测试,及时发现bug。
成本递减、覆盖面递增:回归测试->集成测试->单元测试
单测
Go 内置单元测试支持。所有以 _test.go 结尾的代码会被 Go 识别为单元测试文件。
一个单元测试函数的函数名应当以 Test 开头,并包含 *testing.T 形参。
可通过 func TestMain(m *testing.M) 函数对测试数据进行初始化,并调用 m.Run() 运行单元测试
打桩(mock)机制
给定一个需要打桩的目标函数,创建一个包装函数,调用目标函数时进行“截胡”,改为调用包装函数;使得测试时不必依赖本地文件