2 工程实践|青训营笔记

68 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第2天。

1语言进阶

并发

1多线程程序在一个核的cpu上运行

并行

2多线程程序在多个核的cpu上运行

Go可以充分发挥多核优势高效运行

1.1Goroutine

协程:用户态,轻量级线程,栈KB级别

线程:内核态,线程跑多个协程,栈MB级别

快速 打印 快速提示用多协程

在调用函数前加go关键字

为函数创建协程来运行

time.Sleep()保证子协程执行完之前主协程不退出

乱序输出

1.2 CSP

提倡通过通信共享内存而不是通过共享内存实现通信

通道Channel 队列 提倡

获取临界区 权限 影响程序性能

1.3Channel

引用类型

make(chan 元素类型,[缓冲大小])

分为有无缓冲通道

无缓冲 也称为同步通道

带缓冲解决 子协程 生产快 消费慢 不均衡带来的执行效率问题

defer 延迟资源关闭

通信实现共享内存

1.4 并发安全Lock

多个goroutine同时操作内存资源

lock sync.Mutex

+1前用lock.Lock()获取临界区资源

计算完将临界区权限释放

并发安全问题概率出现 难定位 避免对共享内存进行非并发安全读写操作

1.5WaitGroup

三个方法 Add(delta int) 计数器+delta Done() 计数器-1 Wait() 阻塞直到计数器为0

实现并发任务同步

小结

Goroutine 协程 高并发操作

Channel 通过通信共享内存

Sync包下关键字 并发安全操作 协程同步

2依赖管理

2.0背景

工程项目不肯基于标准库0~1编码搭建

管理依赖库

2.1Go依赖管理演进

GOPATH Go Vendor Go Module

不同环境项目依赖版本不同

控制依赖库的版本

2.1.1GOPATH

环境变量$GOPATH

bin 项目编译的二进制文件 pkg 项目编译中间产物,加速编译 src 项目源码

项目代码直接依赖src下的代码

go get下载最新版本的包到src目录下(1.17不能安装可执行文件 可管理依赖)

GOPATH弊端

A/B依赖某package不同版本 无法实现package的多版本控制

2.1.2 Go Vendor

项目目录下增加vendor文件,所有依赖包副本形式放在$ProjectRoot/vendor

项目依赖寻址方式:vendor=>GOPATH

通过每个项目引入一份依赖的副本 解决了多个项目需要同一个package依赖的冲突问题

问题:无法控制依赖的版本

更新项目又可能出现依赖冲突,导致编译出错

2.1.3 Go Module

通过go.mod文件管理依赖包版本

通过go get/go mod 指令工具管理依赖包

终极目标:定义版本规则和管理项目依赖关系

1.配置文件,描述依赖 go.mod 2.中心仓库管理依赖库 Proxy 3.本地工具 go get/mod

2.3.1依赖配置 go.mod

模块路径 依赖管理基本单元

原生库

单元依赖

-version

语义化版本

MAJOR 大版本 不兼容

MINOR 新增函数功能在MAGOR下兼容

PATCH 代码bug修复

基于commit伪版本 版本前缀 时间戳 哈希码前缀

-indirect

A->B->C

A->B直接依赖

A->C间接依赖 没有直接导入会标识为非直接依赖

-incompatible

主版本2+模块会在模块会在模块路径加/vN后缀

对于没有go.mod文件并且主版本2+的依赖 会+incompatible

2.3.5 依赖分发-回源

依赖分发-Proxy

-变量GOPROXY

PROXY1 ->Proxy2 ->Direct

2.3.工具-go get

go get example.org/pkg

@update 默认 @none 删除依赖 @v1.1.2 tag版本,语义版本 @23dfdd5 特定commit @master 分支最新commit

2.3.8 go mod

init 初始化,创建go.mod文件 download 下载模块到本地缓存 tidy 增加需要的依赖,删除不需要的依赖

依赖管理三要素

1配置文件,描述依赖 go.mod

2中心仓库管理依赖库 Proxy

3本地工具 go get/mod

3测试

回归测试
集成测试 单元测试

3.1单元测试

3.1.1单元测试-规则

测试文件以_test.go结尾

func TestXxx(*testing.T)

初始化逻辑放到Testmain中 测试前:数据装载、配置初始化等前置工作 测试后:释放资源等收尾工作

3.1.2单元测试-例子

-运行

-assert

-覆盖率

-tips

一般覆盖率50~60% 较高80%+

测试分支相互独立、全面覆盖

测试单元粒度足够小,函数单一职责

-依赖

外部依赖=>稳定&幂等

-文件处理

-mock

开源包monkey

快速Mock函数 为一个函数打桩 为一个方法打桩

3.5基准测试

优化代码,需要对当前代码分析

内置测试框架提供基准测试能力

fastrand

4项目实战

4.1需求描述

Entity Relationship Diagram

4.4分层结构

数据层Repository:数据Model,外部数据增删改查

逻辑层Service:业务Entity,处理核心业务逻辑输出

视图层:视图view,处理和外部的交互逻辑

4.5组件工具

Gin高性能go web框架

Go Mod

go mod init

go get

4.6Repository

-index

4.7Service

4.8Controller

4.9Router

4.10运行

小结

项目拆解

代码设计

测试运行