Go 语言进阶 - 工程进阶 | 青训营笔记

106 阅读3分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 2 天

今日内容

学习完了青训营课程 后端入门 - Go 语言原理与实践 中的 Go 语言进阶与依赖管理 和 Go 语言工程实践之测试 之后的一些总结。

课程内容

  1. 语言进阶
  2. 依赖管理
  3. 测试

1. 语言进阶

1.1 Goroutine

  • 并发和并行:

    并发:早期计算机的 CPU 基本为单核,一个 CPU 在同一时刻只能执行一个线程/进程,当系统中有多个线程/进程在执行时,其实就是时间片轮转表现出这些线程/进程在同时运行。并发也就是使用算法将 CPU 的资源合理分配给多个任务,当其中一个任务阻塞时,CPU 可以执行其他的任务。这样会造成的问题就是线程/进程上下文切换的开销比较大。

    并行:并发是针对单核 CPU 提出的,并行针对的是多核 CPU。多核 CPU 每个核心都可以独立运行一个任务,且不同核心之间不会互相干扰。

  • 线程和协程:

    线程:线程是存在于内核态的概念,创建销毁和切换都由操作系统控制,会一定程度上占用系统资源。

    协程:协程运行在线程之上,通过分时复用的方式在线程上运行多个协程,减少操作系统的部分开销

1.2 CSP(Communicating Sequential Processes)

  • 不同线程/进程之间的通信在其他语言中通常以全局变量(共享内存)实现,少有管道的便捷操作

  • 而 go 提倡通过通信共享内存而不是通过共享内存实现通信

1.3 Channel

go 创建 Channel 的方式

  1. var channelName chan channelType 无缓冲管道
  2. 使用 func make(t Type, size ...IntegerType) Type 函数 channelName := make(chan channelType, channelSize) 创建指定缓冲区大小的 Channel

1.4 并发安全 Lock

go 支持互斥量(sync.Mutex)和读写锁(sync.RWMutex),读写锁额外支持 RLock()RUnlock()

1.5 WaitGroup

上一篇文章中讲到过,可能会出现主线程结束了但是协程还没有结束的情况,sync.WaitGroup 相当于是一个计数器,每创建一个协程计数器 +1(Add(delta int)),每一个协程结束计数器 -1(Done()),主线阻塞(Wait())直到计数器为 0

2. 依赖管理

2.1 Go 依赖管理演进

2.1.1 GOPATH
2.1.2 Go Vender
2.1.3 Go Module
  • 通过 go.mod 文件管理依赖包版本
  • 通过 go get/go mod 指令工具管理依赖包

2.2 依赖管理三要素

  1. 配置文件,描述依赖 go.mod
  2. 中心仓库管理依赖库 proxy
  3. 本地工具 go get/mod
  • go get example.org/pkg 用于添加依赖
  • go mod init 初始化,创建 go.mod 文件
  • go mod download 下载模块到本地缓存
  • go mod tidy 添加需要的依赖,删除不需要的依赖

3. 测试

3.1 单元测试

  • 测试文件以 _test.go 结尾
  • func TestXxx(*testing.T)
  • 初始化逻辑放在 func TestMain(*testing.M)

go test fileName.go --cover 可以得到测试覆盖率

3.2 单元测试 - Mock

golang/mock: GoMock is a mocking framework for the Go programming language. (github.com)

3.3 基准测试

具体方法细节建议翻阅文档

testing package - testing - Go Packages