这是我参与「第五届青训营 」伴学笔记创作活动的第 3 天
并发
协程Gorountine: 用户态,轻量级线程,栈MB级别 线程:内核态,线程跑多个携程,栈KB级别
协程使用: 在调用函数前加go关键字 -- 创建协程 阻塞:time.Sleep(time.Second) -- 子协程运行完前主协程不退出
协程之间的通信: 提倡通过通信共享内存而不是通过共享内存而实现通信 channel -- 通道 创建:make(chan 元素类型, [缓冲大小]) 无缓冲 -- 同步
并发安全 Lock:对临界区的控制保证并发安全
WaitGroup -- 计数器实现并发任务的同步 add(delta int) 计数器+delta (开启协程+1) done() 计数器-1 (执行结束-1) wait() 阻塞直到计数器为0 表明所有的并发任务都已完成(主协程)
var wg sync.WaitGroup
wq,Add(5)
for i := 0; i<5; i++ {
go func(j int) {
defer wg.Donr()
hello(j)
}(i)
}
wg.Wait()
依赖管理 Go Module
- 通过 go.mod 文件管理依赖包版本
- 通过 go get/ go mode 指令工具管理依赖包 终极目标:定义版本规则和管理项目依赖关系
三要素
- 配置文件,描述依赖 go.mod
依赖管理基本单元 : module XXX
原生库:go 1.16
单元依赖:require [module path][version/pseudo version]
依赖配置:
- version:语义化版本 && 基于commit伪版本
- indirect:间接依赖
- incompatible:不兼容
- 依赖图:选择最低的兼容版本
- 中心仓库管理依赖库 Proxy 依赖分发
- 本地工具 go get/mod go get example.org/pkg
- @update 默认
- @none 删除依赖
- @v1.1.2 tag版本 语义版本
- @23dfdd5 特定的commit
- @master 分支的最新的commit go mod
- init 初始化
- download 下载模块到本地缓存
- tidy 增加需要的依赖,删除不需要的依赖
测试
回归测试->集成测试(系统功能)->单元测试(单独的函数模块) 从左到右,覆盖率++,成本--
单元测试
规则:
- 所有测试文件以_test.go结尾
- 测试函数 funx TextXxx(*testing.T)
- 初始化逻辑放到TestMain(m *testing.M) 中 Assert包:assert.Equal 代码覆盖率 测试分支相互独立、全面覆盖 测试单元粒度足够小,函数单一职责
依赖
外部依赖 =》 稳定(单元测试相互隔离)&幂等(重复运行测试结果一样)=》Mock
monkey:github.com/bouk/monkey
快速Mock函数: 打桩:打桩函数A去替换另一个源函数B
- 为一个函数打桩
- Patch(target-B, replacement interface{}-A)
- Unpatch(target interface{}-A)
- 为一个方法打桩
基准测试
对代码进行性能分析
项目实践
分层结构
- 数据层:(repository)数据Model,外部数据的增删改查
- 逻辑层:(service)业务Entity,处理核心业务的逻辑输出
- 视图层:(controller)视图view,处理和外部的交互逻辑 组件工具:
- Gin 高性能 go web 框架:github.com/gin-gonic/g…
- Go Mod: go mod init go get gopok.in/gin-gonic/gin.v1@v1.3.0
repository - index
元数据 数据行 --> 索引 内存Map
var topicDao *TopicDao
//单例模式
var topicOnce sync.Once
func NewTopicDaoInstance() *TopicDao {
topicOnce.Do(
func() {
topicDao = &TopicDao{}
})
return topicDao
}
func (*TopicDao) QueryTopicById(id int64) (*Topic, error) {
var topic Topic
err := db.Where("id = ?", id).Find(&topic).Error
if err != nil {
util.Logger.Error("find topic by id err:" + err.Error())
return nil, err
}
return &topic, nil
}
service
流程:参数校验 -> 准备数据 -> 组装实体