这是我参与「第三届青训营 -后端场」笔记创作活动的的第2篇笔记
- 并发编程
- 并发与并行
- 并发:多线程程序在一个核的cpu上运行
- 并行:多线程程序在多个核的cpu上运行
- 协程与线程
- 携程:用户态,轻量级线程,栈KB级别
- 线程:内核态,线程跑多个协程,栈MB级别
- 协程间通信:提倡通过通信共享内存而不是通过共享内存实现通信
- 通道/Channel
- 创建:
make(chan elemType,[buffer size])- 无缓冲通道
make(chan int)使接收方和发送方同步化 - 有缓冲通道
make(chan int,2)缓冲区满会阻塞 可以解决生产者和消费者速度不均衡造成的效率问题
- 无缓冲通道
- 创建:
- 并发安全Lock
lock sync.Mutexlock.Lock()lock.Unlock()
- WaitGroup
var wg sync.WaitGroupAdd(delta int)计数器+deltaDone()计数器-1Wait()阻塞直至计数器为0
- 通道/Channel
- 并发与并行
- 依赖管理
- 版本迭代
- GOPATH
- 项目代码直接依赖src下代码
- go get下载最新版本的包到src目录下
- bin 项目编译的二进制文件
- pkg 项目编译的中间产物,加速编译
- src 项目源码
- 弊端:无法实现package的多版本控制
- GO Vendor
- 项目目录下增加vendor文件夹,所有依赖包副本形式放在$ProjectRoot/vendor
- 依赖寻址方式: vendor => GOPATH
- 通过每个项目引入一份依赖的副本,解决了多个项目需要同一个package依赖的冲突问题
- 问题:无法控制依赖版本。更新项目有可能出现依赖冲突,导致编译出错
- Go Module
- 通过go.mod文件管理依赖包版本
- 通过go get/go mod指令工具管理依赖包
- 终极目标:定义版本规则和管理项目依赖关系
- GOPATH
- 依赖管理三要素
- 配置文件,描述依赖
go.mod - 中心仓库管理依赖库
Proxy - 本地工具
go get/mod
- 配置文件,描述依赖
- go mod 用法
init初始化,创建go.mod文件download下载模块到本地缓存tidy增加需要的依赖,删除不需要的依赖
- 版本迭代
- 测试
- 单元测试
- 规则
- 所有测试文件以
_test.go结尾 func TestXxx(t *testing.T)- 初始化逻辑放在
TestMain中,在包层面生效
func TestMain(m *testing.M){ // 测试前:数据装载、配置初始化等前置工作 code := m.Run() // 测试后:释放资源等收尾工作 os.Exit(code) } - 所有测试文件以
- 规则
- Mock测试
func TestProcessFirstLineWithMock(t *testing.T){ monkey.Patch(ReadFirstLine, func() string{ //打桩 return "line110" }) defer monkey.Unpatch(ReadFirstLine) //卸桩 line := ProcessFirstLine() assert.Equal(t,"line000",line) } - 基准测试 即压力测试
- 单元测试
- 项目实践
- 分层结构
- 数据层Repository:数据Model,外部数据的增删改查
- 逻辑层Service:业务Entity,处理核心业务逻辑输出
- 视图层Controller:视图View,处理和外部的交互逻辑
- 单例模式
sync.Once多并发场景只执行一次,减少资源浪费
var topicOnce sync.Once topicOnce.Do( func(){ topicDao = &TopicDao{} } ) - service层:参数校验->准备数据->组装实体
- Router: 使用gin搭建框架
- 初始化数据索引
- 初始化引擎配置
- 构建路由
- 启动服务
- 分层结构
- homework
- 支持发布帖子
- 本地ID生成需要保证不重复、唯一性
- Append文件,更新索引,注意Map的并发安全问题