这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天
语言进阶
Goroutine
协程:用户态,轻量级线程,栈MB级别
线程:内核态,线程跑多个协程,栈KB级别
go语言使用协程时只需要在在函数名之前加入go关键字,但是需要注意的是打印的时候是乱序输出的。
CSP(Communicating Sequential Proccesses)
go语言提倡通过通信共享内存而不是通过共享内存而实现通信
Channel
make(chan 元素类型,[缓冲大小])
- 无缓冲通道 make(chan int)
- 有缓冲通道 make(chan int , 2)
并发安全 Lock
通过加锁lock sync.Mutex
来解决并发安全问题
WaitGroup
go语言中可以通过WaitGroup来实现并发任务的同步,通过维护一个计数器来实现,包括三个主要函数
- Add(delta int) 计数器 +delta
- Done() 计数器-1
- Wait() 阻塞直到计数器为0
实例:
依赖管理
Go依赖管理演进
GOPATH -> Go Vendor -> Go Module
不同环境(项目)依赖的版本不同
控制依赖库的版本
GOPATH
- 环境变量 $GOPATH
- bin 项目编译的二进制文件
- pkg 项目编译的中间产物,加速编译
- src 项目源码
- 项目代码直接依赖 src 下的代码
- go get 下载最新版本的包到src目录下
无法实现package的多版本控制
Go Vendor
依赖寻址地址 vendor => GOPATH
通过每个项目引入一份依赖的副本,解决了多个项目需要同一个package依赖的冲突问题
问题:
无法控制依赖的版本
更新项目有可能出现依赖冲突,导致编译出错
Go Module
通过go.mod文件管理依赖包版本
通过go get/go mod指令工具管理依赖包
依赖管理三要素
- 配置文件,描述依赖 go.mod
- 中心仓库管理依赖库 Proxy
- 本地工具 go get/mod
对于不同项目依赖了同一项目的不同版本时,最终编译时会选择依赖项目的最低兼容版本。
测试
回归测试
集成测试
单元测试
规则
- 所有测试文件都以_test.go结尾
- func TestXxx(*testing.T)
- 初始化逻辑放到TestMain中
Mock
可以使用monkey对函数或方法进行打桩,从而不再依赖本地文件
基准测试
在高并发场景可以用fastrand来替代rand
项目实战
需求设计
需求描述,E-R图,
分层结构:
- 数据层:数据Model,外部数据的增删改查
- 逻辑层:业务Entity,处理核心业务逻辑输出
- 视图层:视图View,处理和外部的交互逻辑
代码开发
Service:参数校验 -> 准备数据 -> 组装实体
Controller:构建View对象,业务错误码
Router:初始化数据索引,初始化引擎配置,构建路由,启动服务
测试运行
go run server.go
go map的并发安全问题