go工程实践 | 青训营笔记

53 阅读1分钟

这是我参与「第五届青训营 」笔记创作活动的第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()

image.png

现象解释:

并发带来的问题:回忆一条指令的执行过程:

取出变量的值,对变量值进行修改,将值存回变量 将变量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 命令管理依赖

image.png

image.png

单元测试

测试的意义

项目部署之前进行测试,及时发现bug。

成本递减、覆盖面递增:回归测试->集成测试->单元测试

单测

Go 内置单元测试支持。所有以 _test.go 结尾的代码会被 Go 识别为单元测试文件。

一个单元测试函数的函数名应当以 Test 开头,并包含 *testing.T 形参。

可通过 func TestMain(m *testing.M) 函数对测试数据进行初始化,并调用 m.Run() 运行单元测试

打桩(mock)机制

给定一个需要打桩的目标函数,创建一个包装函数,调用目标函数时进行“截胡”,改为调用包装函数;使得测试时不必依赖本地文件

工程实战:Gin