Go语言工程进阶 | 青训营笔记

95 阅读4分钟

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

1. Go语言进阶

并发VS并行

并发:多线程程序在一个核的cpu上运行;并行:多线程程序在多个核的cpu上运行 Go可以充分发挥多核优势,高效运行

1.1 Goroutine

协程:用户态,轻量级线程,栈MB级别。 线程:内核态,线程跑多个协程,栈KB级别。 协程示例:image.png

1.2 CSP

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

1.3 Channel

make(chan 元素类型,[缓冲大小]) 无缓冲通道 make(chan int) 有缓冲通道 make(chan int,2)

image.png

示例: A 子协程发送0~9数字, B 子协程计算输入数字的平方, 主协程输出最后的平方数。

image.png

image.png

1.4 并发安全Lock

示例:对变量执行2000次+1操作,5个协程并发执行

image.png

image.png

1.5 WaitGroup

计数器:开启协程;执行结束-1;主协程阻塞直到计数器为0.

image.png

2.依赖管理

2.0 背景

image.png 工程项目不可能基于标准库0~1编码搭建,要学会管理依赖库。

2.1 Go依赖管理演进

目的:不同环境(项目)依赖的版本不同;控制依赖库的版本

image.png

2.1.1 GOPATH

它是一个环境变量 $GOPATH

image.png

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

go get 下载最新版本的包到src目录下

GOPATH-弊端

image.png

场景:A和B依赖于某一package的不同版本。

问题:无法实现package的多版本控制。

2.1.2 Go Vendor

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

依赖寻址方式:vendor => GOPATH

image.png

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

Go Vendor-弊端

image.png

问题:无法控制依赖的版本;更新项目又可能出现依赖冲突,导致编译出错。

2.1.3 Go Module

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

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

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

2.2依赖管理三要素

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

2.中心仓库管理依赖库 Proxy

3.本地工具 go get/mod

2.3.1 依赖配置-go.mod

image.png

依赖标识:[Module Path][Version/Pseudo-version]

2.3.2 依赖配置-version

语义化版本

MAJOR. {MAJOR}.{MINOR}.${PATCH}

V1.3.0 V2.3.0

基于commit伪版本

vX.0.0-yyyymmddhhmmss-abcdefgh1234

2.3.3 依赖配置-indirect

image.png

A->B->C: A->B 直接依赖; A->C 间接依赖

2.3.4 依赖配置-incompatible

image.png

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

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

3.测试

测试是避免事故的最后一道屏障 image.png 测试类型:

image.png

3.1 单元测试

image.png

3.1.1 单元测试规则

所有测试文件以_test.go 结尾

image.png

func TestXxx(*testing.T)

image.png

初始化逻辑放到 TestMain中

image.png

3.1.2 单元测试-例子

image.png

image.png

3.1.3 单元测试-运行

go test [flags][packages]

image.png

3.1.4 单元测试-assert

image.png

image.png

image.png

3.1.5 单元测试-覆盖率

覆盖率能够衡量代码经过了足够的测试、评价项目的测试水准、评估项目是否达到了高水准测试等级。

image.png

image.png

image.png

image.png

image.png

一般项目覆盖率:50~60%,较高为80%+。

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

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

3.2 单元测试-依赖

image.png

                          外部依赖  =>  稳定&幂等

3.3 单元测试-文件处理

image.png

image.png

image.png

3.4 单元测试-Mock

monkey包:github.com/bouk/monkey

快速Mock函数:为一个函数打包;为一个方法打桩。

image.png

对ReadFirstLine打桩测试,不再依赖本地文件

image.png

image.png

3.5 基准测试

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

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

3.5.1 基准测试-例子

随机选择执行服务器

image.png

3.5.2 基准测试-运行

image.png

image.png

3.5.3 基准测试-优化

image.png

image.png

4.项目实战

4.1 需求描述

社区话题页面

展开话题(标题,文字描述)和回帖列表

暂不考虑前端页面实现,仅仅实现一个本地web服务

话题和回帖数据用文件存储

4.2 需求用例

浏览消费用户

image.png

4.3 ER图-Entity Relationship Diagram

image.png

4.4 分层结构

image.png

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

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

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

4.5 组件工具

Gin高性能 go web 框架

github.com/gin-gonic/g…

Go Mod

go mod init

go get gopkg.in/gin-gonic/gin.v1@v1.3.0

4.6 Repository

Topic

image.png

Post

image.png

4.6 Repostory-index

image.png

image.png

初始化话题数据索引

image.png

4.6 repository-查询

image.png

索引:话题ID

数据:话题

4.7 Service

image.png

实体

image.png

流程

代码流程编排

image.png

image.png

并行处理

image.png

4.8 Controller

image.png

构建View对象

业务错误码

4.9 Router

image.png

流程:1.初始化数据索引 2.初始化引擎配置 3.构建路由 4.启动服务

4.10 运行

运行测试:go run server.go

5 总结

这是本次学习的所有内容,对于Go工程实践有大量的实践内容。其中对于项目制作上有一定的难度,希望自己可以完成。