这是我参与「第五届青训营 」笔记创作活动的第2天
Go并发基础
Goroutine
协程: 用户态,轻量级线程,栈MB级别
线程: 内核态,线程跑多个协程,栈KB级别
补充
关于用户态和内核态
先给不了解内核态、用户态的简单介绍一下,我们在什么时候会提到这两个概念。
例如我们的应用程序需要从磁盘读取某个文件的数据,此时并不是直接从磁盘加载到应用内存中,而是:
- 先将数据从「磁盘」复制到「内核 Buffer」
- 再将数据从「内核 Buffer」复制到「用户 Buffer」
以上就是用户态和内核态的概念。首先我们给他下个定义,这两个态是操作系统的运行级别。
然后我们知道,我们写的程序,最终运行的时候实际都会被编译、解释成一条一条的 CPU 指令被 CPU 执行。
用户态、内核态的指令都是 CPU 都在执行,所以我们可以换个说法,实际上这个态代表的是当前 CPU 的状态。那既然这些指令最终都由 CPU 执行,那对其区分的理由是什么呢?
那是因为,CPU 指令根据其重要的程度,也分为不同的权限。有一些指令执行失败了无关痛痒,而有一些指令失败了会导致整个操作系统崩溃,甚至需要重启系统。如果将这些指令随意开放给应用程序的话,整个系统崩溃的概率将会大大的增加。
来源:zhuanlan.zhihu.com/p/447488276
使用go关键字即可使用协程
go func(){}
CSP
提倡通过通信共享内存
channel
make (chan 类型,[缓冲大小])
//有缓冲通道 同步通道
make (chan int)
//无缓冲通道 类似sheng'ca'h
make (chan int,1)
Lock
lock通过实现临界区来保证并发安全
lock.Lock()
//临界区
lock.Unlock()
WaitGroup
优雅地退出主协程
内部维护了一个计数器,主协程阻塞直到计数器为0
依赖管理
- GOPATH:直接依赖src,无法实现多版本控制
- GO Vendor:项目目录新增vendor文件,解决多个项目需要一个package依赖的冲突问题,但无法控制依赖的版本
- GOMODLE:通过go.mod文件管理
工程实践
测试
- 回归测试:还原使用场景
- 集成测试:对系统功能验证
- 单元测试:对代码模块进行测试
go test工具
Go语言中的测试依赖go test命令。编写测试代码和编写普通的Go代码过程是类似的,并不需要学习新的语法、规则或工具。
go test命令是一个按照一定约定和组织的测试代码的驱动程序。在包目录内,所有以_test.go为后缀名的源代码文件都是go test测试的一部分,不会被go build编译到最终的可执行文件中。
在*_test.go文件中有三种类型的函数,单元测试函数、基准测试函数和示例函数。