这是我参与「第五届青训营 」伴学笔记创作活动的第 2天
一、本堂课重点内容:
本节课程主要分为四个方面:
- 语言进阶
- 依赖管理
- 单元测试
- 项目实战
二、详细知识点介绍:
语言进阶
Goroutine
协程:用户态,轻量级线程,栈KB级别
线程:内核态,线程跑多个协程,栈MB级别
- CSP(Communicating Sequential Processes)
提倡通过通信共享内存而不是通过共享内存而实现通信
Channel
make(chan 元素类型,[缓存大小])
无缓冲通道 make(chan int)
有缓存通道make(chan int,2) 生产·消费问题
并发安全 Lock
var lock sync.Mutex
通过lock.Lock()和lock.Unlock()实现协程的互斥操作,达到并发安全
WaitGroup
计数器:开启协程+1;执行结束-1;主协程阻塞直到计数器为0
//快速打印hello goroutine:0-4
func hello(i int) {
println("hello world : " + fmt.Sprint(i))
}
//不使用WaiGroup
func HelloGoRoutine() {
for i := 0; i < 5; i++ {
go func(j int) {
hello(j)
}(i)
}
time.Sleep(time.Second)
}
//使用WaiGroup更优雅
func ManyGoWait() {
var wg sync.WaitGroup
wg.Add(delta:5)
for i := 0; i < 5; i++ {
go func(j int) {
defer wg.Done()
hello(j)
}(i)
}
wg.Wait()
}
依赖管理
背景
工程项目不可能基于标准库0-1编码搭建,更加注重逻辑层面编码,因此要依赖管理
Go依赖管理演进
GOPATH->Go Vendor->Go Module
不同环境(项目)依赖的版本不同,要控制依赖库的版本
1.环境变量$GOPATH
$GOPATH
├── bin //项目编译的二进制文件
├── pkg //项目编译的中间产物,加速编译
└── src //项目源码
弊端:若场景A和B依赖于某一package的不同版本,无法实现package的多版本控制
项目代码直接依赖src下的代码
go get下载最新版本的包到src目录下
2.GoVender
弊端:无法控制依赖的版本。更新项目又可能出现依赖冲突,导致编译出错。
3.GoModule
可以定义规则管理关系。
Go Module实践
依赖管理三要素
- 配置文件,描述依赖 go.mod
version:
语义化版本${MAJOR}.${MINOR}.${PATCH}
基于commit伪版本vX.0.O-yyyymmddhhmmss-abcdefgh1234(时间戳+哈希码)
- 中心仓库管理依赖库 Proxy
- 本地工具 go get/mod
go mod:
init 初始化,创建go.mod文件 download 下载模块到本地缓存 tidy 增加需要的依赖,删除不需要的依赖
单元测试
规则:
- 所有测试文件以_test.go 结尾
- func TestXxx(*testing.T)
- 初始化逻辑放到TestMain中
可以增加--cover参数来显示覆盖率
Mock
常用 monkey : github.com/bouk/monkey
基准测试
基准测试用于对代码进行性能分析。
以Benchmark开头,Resttimer重置计时器,runparallel是多协程并发测试。
在并发情况下rand为了保证并发安全和随机性有了全局锁,性能下降,可以使用fastrand提升性能。
三、实践练习例子:
青训营话题页开发
- 进行需求分析,画出需求用例和ER图
- 选择分层结构,这里选择数据-逻辑-视图的的结构
- 选择组件工具,使用go mod进行依赖管理,导入gin框架
- 设计Repository,主要有Topic结构和Post结构,使用map来进行索引
- 构建初始化数据索引函数
- 构建数据查询函数
- 设计构建Service实体
- 进行具体Service处理代码流程编排
- 构建View对象,返回最终信息
四、课后个人总结:
本次课程知识点较多,需要慢慢消化吸收。