这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天
课堂笔记(Go语言进阶与依赖管理&Go语言工程实践之测试)
本节课重点内容: 从工程实践角度了解Go在企业设计开发过程中涉及的基础知识点
1.并发编程
- 并发:多线程程序在一个核的cpu上运行
- 并行:多线程程序在多个核的cpu上运行
协程与线程程的分别
线程可以并发的运行多个协程
- 协程:用户态、轻量级线程、栈MB级别
- 线程:内核态、线程跑多个协程、栈KB级别
Go语言提倡通过通讯共享内存而不是通过共享内存而实现通讯
通过共享内存实现通讯需要使用互斥量加锁,不同的协程之间可能发生数据静态,在一定程度上影响程序的性能
通过通讯共享内存
通过通讯共享内存需要使用channel,channel需要使用make(chan 元素类型, [缓冲大小])这种方式申请空间,channel是引用类型,channel分为两种:
-
无缓冲通道 make(chan int)
-
有缓冲通道 make(chan int, 2)
无缓冲通道实现不同协程的同步执行,有缓冲通道实现不同协程的异步执行
共享内存实现通讯
共享内存实现通讯需要使用锁,相关函数在sync包中
并发安全Lock
- 声明一个锁:lock sync.Mutex
- 加锁:lock.Lock()
- 解锁:lock.Unlock()
WaitGroup
Go语言也可以使用waitgroup实现并发任务的同步
- 声明一个计数器:var wg sync.WaitGroup
- 设置计数器:wg.Add(5)
- 计数器减1:defer wg.Done()
- 计数器为0:wg.Wait()
将计数器设置为协程数量,每个协程完成后计数器减1,当计数器不为0时wg.Wait()会阻塞,直到计数器为0也就是所有协程都结束
2.依赖管理
Go的依赖管理经历了三个阶段,不同环境的依赖的版本不同
- GOPATH
- Go Vender
- Go Module
目前新版本的Go语言使用Go Module对依赖进行管理
Go Module
- 通过go.mod文件管理依赖包版本
- 通过go install/go mod指令工具管理依赖包
依赖管理三要素
- 配置文件,描述依赖 go.mod
- 中心仓库管理依赖库 Proxy
- 本地工具 go install/mod
3.测试
- 回归测试
- 集成测试
- 单元测试
这三种测试从上到下,覆盖率逐层变大,成本却逐层降低
单元测试
单元测试规则:
- 所有测试文件以_test.go结尾
- func TestXxx(*testing.T)
- 初始化逻辑放到TestMain中
单元测试运行指令:
go test [flags] [packages]
单元测试可以使用一个开源包方便的判断输出是否符合期望:github.com/stretchr/testify/assert assert.Equal(t, expectOutput, output)
单元测试覆盖率:go test judgment_test.go judgment.go --cover
- 一般覆盖率:50%~60%,较高覆盖率80%+
- 测试分支相互独立、全面覆盖
- 测试单元粒度足够小,函数单一职责
单元测试-Mock
monkey:github.com/bouk/monkey
Mock函数可以快速为一个函数或方法打桩,使测试的函数或方法不依赖本地文件
基准测试
优化代码,对当前代码分析,测试代码的运行速度
项目实践
需求描述
- 展示话题(标题、文字描述)和回帖列表
- 不考虑前端页面实现,仅仅实现一个本地web服务
- 话题和回帖数据用文件存储
需求用例
用户可以查看话题以及话题所对应的回帖的列表
ER图
话题和回帖的结构体属性如上
分层结构
- 数据层:数据Model,外部数据的增删改查
- 逻辑层:业务Entity,处理核心业务逻辑输出
- 视图层:视图view,处理和外部的交互逻辑