这是我参与「第三届青训营 -后端场」笔记创作活动的第2篇笔记
1. 语言进阶
0.并发VS并行
- 并发:多线程程序在一个核的cpu上运行
- 并行:多线程程序在多个核的cpu上运行
Go可以充分发挥多核优势,高效运行
1.1Goroutine
| 协程 | 用户态 | 栈MB级别 |
| 线程 | 内核态 | 栈KB级别 |
协程:轻量级线程; 线程跑多个协程
1.2.CSP(Communicating Sequential Processes)
- 通过通信共享内存(channel )
- 通过共享内存实现通信
提倡通过通信共享内存而不是通过共享内存而实现通信
1.3. Channel
- 是一种引用类型
- 创建:make(chan 元素类型, [缓冲大小])
- 无缓冲通道(同步通道)
- 有缓冲通道(生产消费模型)
- 例子
- 带缓冲的channel可以解决生产者和消费者的消费速度带来的不均衡的问题
1.4. 并发安全Lock
- sync库
lock sync.Mutex
lock.Lock()
...
lock.Unlock()
1.5 WaitGroup
- 实现写成之间的同步
- sync库
- 三个方法
2.依赖管理
2.1 Go依赖管理演进
2.1.1GOPATH
弊端:无法实现package的多版本控制
2.1.2 Go Vendor
弊端:
2.1.3Go Module
- 通过go.mod文件管理依赖包版本
- 通过go get/ go mod 指令工具管理依赖包
终极目标:定义版本规则和管理项目依赖关系
2.2依赖管理三要素
2.3
2.3.1依赖配置-go.mod
- 介绍go.mod文件的三个部分
2.3.2依赖配置- version
- 语义化版本
- 基于commit伪版本
2.3.3依赖配置-indirect
2.3.4依赖配置-incompatible
- 标识出来可能存在一些代码不兼容的版本问题
2.3.4依赖配置-依赖图
- 选择最低兼容版本
2.3.5依赖分发-回源
Proxy
- 实现了一个稳定、可靠的依赖分发
2.3.6 依赖分发-变量GOPROXY
2.3.7工具-go get
2.3.8工具-go mod
3.测试
- 回归测试:比如刷一下抖音,看看评论是否有出现类似这样的
3.1单元测试
3.1.1 规则
- 文件名规范
- 测试函数名的规范
- 初始化逻辑放到TestMain中
- 学习一下TestMain的用法
- 参数:
*testing.M
assert
- 一个包,可以调用包里面的assert.Equal()判断是否相等
- 我愿意称呼它为判断包
评估单元测试:用代码覆盖率
利用参数:
-- cover
go test xxx_test.go xxx.go --cover
可以在xxx_test.go里面写多个测试函数对代码进行测试,增加代码的覆盖率
3.2单元测试-依赖
- 幂等:重复运行一个测试的时候,运行的结果都是一样的
- 稳定:单元测试能在任何时间,任何条件下都可以独立运行
3.3 单元测试-文件处理
- 一个例子,折射一个问题:万一文件被篡改了,单元测试的结果就跟之前文件没有被篡改的情况不一致了,依赖与本地文件
3.4单元测试-Mock测试
- 常用的Mock组件:monkey
- 用一个函数替换本地的源文件:实现了测试完全不依赖于本地文件
3.5基准测试
- 测试函数运行时的性能和CPU的损耗
- 使用方法类似于单元测试
- 函数名以
Benchmarkxxx开头 - 入参是
*testing.B
3.5.1例子
3.5.3优化
如果需要用到随机数的场景,推荐使用一下fastrand,替换掉rand
4.项目实战
主要讲解项目开发的流程和逻辑
4.1需求描述
4.2需求用例分析
4.3ER图
- Topic和Post是1对多的关系
4.4分层结构
4.5组件工具
4.6Repository层(数据层)
- 实现两个函数分别对两个结构体进行扫描查询
index
- 构建两个索引,通过索引可以很快的定位到数据
- 初始化话题数据索引
- 初始化回帖数据的索引(自己实现一下)
查询操作
- 因为有了索引,所以可以直接根据id的key来拿数据就行了
- sync.Once:通常用在高并发模式下只执行一次的情况,单例模式
- 参照上面的代码,实现一下查询回帖列表的方法(很简单直接从map里面取出数据就行了)
4.7Service(逻辑层)
页面的信息:PageInfo,有两个实体Topic和PostList
实现逻辑:参数校验 ->通过respository层拿数据 ->组装实体
- prepareInfo函数:通过respository层获取活体信息和用户响应信息
- 因为话题信息跟回帖信息之间没有相互依赖的关系,所以就可以并行的进行处理
4.8Controller
跟用户进行交互
- 构建VIew对象(状态码,错误信息那些)
- 业务错误码
至此整个业务逻辑已经完成了
4.9Router
流程
- 初始化数据索引
- 初始化引擎配置
- 构建路由
- 启动服务