go进阶 | 青训营笔记

72 阅读4分钟

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

一、本堂课重点内容:

  • Go语言进阶
  • Go语言依赖管理
  • Go语言测试

二、详细知识点介绍:

GO进阶

并行与并发

  • 并行:多线程程序在一个核的cpu上运行
  • 并发:多线程程序在多个核的cpu上运行

协程与进程

  • 协程:用户态,轻量级线程,栈MB级别。
  • 线程:内核态,线程并发跑多个协程,栈KB级别。

go语言一次可以创建上万的协程,这也是go语言更适合高并发场景的原因。

协程间的通信

go提倡通过通信共享内存,而不是通过共享内存而实现通讯。

go也保留了过共享内存而实现通讯,但这需要一些互斥量去进行加锁,限制临界区的权限,这会在一定程度上影响程序的性能。

go使用了channel来进行通信 。

Channel

channel是一种引用类型,需要使用make进行创建。

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

  • 无缓冲通道 make(chan int)
  • 有缓冲通道 make(chan int, 2)

并发安全

主要是对共享内存的不安全操作所引起的,因为这是一个未定义的行为。例如

2_1.png

2_2.png

2_3.png

所以需要我们对临界资源进行控制,来并发安全的共享内存。

阻塞

上面的代码是用sleep来暴力阻塞,事实上更优雅的方式是使用计数器。

2_4.png

开启协程时计数器+1,执行结束时-1,主协程阻寒直到计数器为0,表明所有的并发任务都已完成。

依赖管理

GOPATH

GOPATH是go的系统变量,即go项目的工作区。

其中有以下三个关键文件

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

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

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

弊端:可能有多个项目依赖于同一个包的不同版本,所以GOPATH无法实现package的多版本控制。

GO Vendor

  • 项目目录下增加vendor文件,所有依赖包副本形式放在$ProjectRoot/vendor
  • 依赖寻址方式:vendor=>GOPATH

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

弊端:

2_5.png

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

Go Module

  • 通过go.mod文件管理依赖包版本
  • 通过go get/go mod 指令工具管理依赖包
  • 终极目标:定义版本规则和管理项目依赖关系
  1. 配置文件,描述依赖 go.mod
  2. 中心仓库管理依赖库 Proxy
  3. 本地工具 go get/mod
配置-go.mod

version

语义化版本

$(MAJOR).$(MINOR).$(PATCH)

例如 V1.3.0 V2.3.0

基于commit伪版本 vX.0.0-yyyymmddhhmmss-abcdefgh1234

时间戳yyyymmddhhmmss也就是提交Commit的时间,最后是校验码(abcdefabcdef),包含12位的哈希前缀;每次提交commit后Go都会默认生成一个伪版本号。

例如

v0.0.0-20220401081311-c38fb59326b7 v1.0.0-20201130134442-10cb98267c6c

仓库-proxy

Go Proxy是一个服务站点, 它会缓源站中的软件内容,缓存的软件版本不会改变 并且在源站软件删除之后依然可用,从而实现了供"immutability"和"available“的依赖分

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

测试

单元测试

单元测试主要包括输入,测试单元,输出,以及校对,单元的概念比较广,包括接口,函数,模块等

单元测试能保证质量和提升效率。

规则
  • 所有测试文件以_test.go结尾
  • func TestXxx(*testing.T)
  • 初始化逻辑放到TestMain中
覆盖率

即实际测试运行过的代码占比。

  • 一般覆盖率:50%~60%,较高覆盖率80%+。
  • 测试分支相互独立、全面覆盖。
  • 测试单元粒度足够小,函数单一职责。
依赖

单元测试对依赖有两个目标,一个是幂等(重复运行测试的结果是一样的),另一个是稳定(单元测试能在任何时间任何函数运行)。

Mock

如果一个测试是通过本地文件数据进行,那么这个测试便是依赖于本地文件,当这个文件被删除或者异常,就可能发生意外。

Monkey是一个用于Mock的package,通过Monkey进行打桩测试,可以不在依赖本地文件。

社区话题页面:

需求

  • 展示话题(标题,文字描述)和回帖列表
  • 暂不考虑前端页面实现,仅仅实现一个本地web服务
  • 话题和回帖数据用文件存储

分析

E_R图

2_7.png

分层结构

s_6.png

  • 数据层:数据Model,外部数据的增删改查
  • 逻辑层:业务Entity, 处理核心业务逻辑输出
  • 视图层:视图View,处理和外部的交互逻辑