2 工程实践
3 测试
3.1 测试粒度
从上至下覆盖率逐层增大,成本降低
回归测试:QA同学通过终端回归固定场景
集成测试:对系统功能
单元测试:面对测试开发阶段,对函数模块测试
3.2 Mock
工具: monkey
可以实现用打桩函数替换原函数,不依赖本地文件进行测试
func Patch
func Unpatch(){ //卸载打桩函数
...
}
实际使用是 defer monkey.Unpatch(functionName)
在运行时,将运行中函数的地址替换成打桩函数,并且手动设置输入和预期结果
3.3 基准测试 bench
测试程序性能和cpu的损耗
//函数传入参数是 b *testing.B
b.ResetTimer()
//串行测试就正常执行
for i := 0; i < b.N; i++ {
Select()
}
//并行测试需使用函数 b.RunParallel()
b.RunParallel(func(pb *testing.PB){
for pb.Next(){
Select()
}
})
实验表明,并行测试时性能反而更差,因为Select()中有rand函数,随机函数持有全局锁,降低了并发的性能,可通过使用fastrand()改进
4 项目开发
需求用例
type Topic struct{
Id int64 `json:"id"`
Title string `json:"title"`
Content string `json:"content"`
CreateTime int64 `json:"create_time"`
}
type Post struct{
Id int64 `json:"id"`
TopicId int64 `json:"topic_id"`
Content string `json:"content"`
CreateTime int64 `json:"create_time"`
}
分层结构
由下自上分别是以下三部分,
Repository:数据层主要面向service层,对其透明,底层实现改变对其接口Model可不改变
Service:接收Repository的数据作打包封装,形成Entity
Controller:包装上游的数据格式,形成API
具体实现
Repository:
read data from file or database and form aimed data structure
define the function DaoInstance() and corresponding method
Dao:
sync.Once是单例模式的运用,适用于高并发场景,减少存储的浪费
Service:
实现逻辑:参数校验(合法性) -> 准备数据 -> 组装实体
use the funciton of repository to query data and check validity
Controller:
focus more on error handling
5 课后作业
几个关键点
新增发布帖子功能
本地Id生成需要保证唯一性
Append文件,更新索引,注意Map的并发安全问题
思考及实现
按分层结构增加代码
首先是repository层
- 在db_init增加rwMUTEX
- 在post文件增加InitPost(),主要逻辑是现在文件内写入,然后加锁保护,根据是否已存在主题加入到索引
其次是service层
- 单独增加publish_post.go
- 关键性的id问题使用了包idWorker
然后是controller层
- 单独增加publish_post.go
- 增加方法
最后在server.go中增加POST方法