Go语言进阶和测试 | 青训营笔记

72 阅读4分钟

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

Go语言进阶与依赖管理

语言进阶

并发和并行

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

协程和线程

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

线程:内核态,线程可以并发多个协程,栈MB级别

创建协程

在函数调用的前面,加上 go关键字,即可创建协程

CSP (Communicating Sequential Processes)

这是协程之间的通信

2023-01-19-21-33-40-image.png

Go语言提倡通过通信共享内存,而不是通过共享内存而实现通信

    一般而言,通过共享内存而实现通信的性能较前者弱

Channel

这是一个引用类型,需要使用make关键字创建

包括有缓和无缓通道两类

2023-01-19-21-34-42-image.png

Lock 并发安全

2023-01-19-21-35-28-image.png

尽量避免对于共享内存进行读写操作

WaitGroup

与 Lock 一样处于 sync 包下

实现并发任务的同步

2023-01-19-21-35-58-image.png

Go依赖管理

控制依赖库的管理

Go PATH

弊端 当两个项目依赖某一package的不同版本,无发实现package的多版本控制

Go Vendor

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

B0D9C238-BC3A-4D64-9A6A-919B41CB8B5D.png

可能导致编译错误

Go Module

通过 go.mod 文件管理依赖包版本 通过 go get/go mod指令工具管理依赖包 可以实现 定义版本规则和管理依赖关系 依赖管理

三要素

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

类似于Maven

依赖版本

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

MAJOR: 是大版本,各个大版本之间可以不兼容   

MINOR: 一般是新增函数和功能

PATCH: 代码bug的修复

Go语言工程实践之测试

单元测试

规范

  1. 所有测试文件以 _test.go 结尾
  2. 所有测试函数以 func TestXxx (*testing.T) 命名
  3. 初始化逻辑放到 func TestMain(m *testing.M)

覆盖率

Command

  • go test 执行测试
  • --cover 返回覆盖率

Tips

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

Mock测试

外部依赖

2023-01-17-23-21-49-image.png

外部依赖 => 稳定&幂等

    幂等 => 多次测试结果相同

打桩

monkey:github.com/bouk/monkey

进行打桩替换,进而实现不依赖本地文件

基准测试

功能

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

使用

  • Go语言内置测试框架,提供了基准测试的能力

    • 用以测试程序性能
  • 函数名以 Benchmark开头

  • 入参 *testing.B

举例

rand函数

// 随机选择服务器
import (
    "math/rand"
)


var ServerIndex [10]int


func InitServerIndex() {
    for i := 0; i < 10; i++ {
        ServerIndex[i] = i + 100
    }
}


func Select() int {
    return ServerIndex[rand.Intn(10)]
}

假设我们有10个服务器列表,每次随机选择一个执行

2023-01-19-21-42-45-image.png

通过测试,我们发现多协程并发测试比穿行测试慢

原因是rand函数为了保证并发安全性和全局随机性,持有一把全局锁

2023-01-19-21-43-27-image.png

字节为了解决这一随机的性能问题,开源了高性能随机数方法 fastrand

性能提升非常大

思路是牺牲了一定的数列随机性

项目实战

需求分析

需求描述

  • 做一个论坛模块
  • 展示话题和回帖列表
  • 仅实现本地 web 服务
  • 话题和回帖用文件的形式存储

ER 图 - Entity Relationship Diagram

Topic

  • ID
  • Title
  • Content
  • Poster
  • CreateTime

PostList

  • ID
  • TopicID
  • Content
  • Poster
  • CreateTime

二者之间是一对多的关系

分层结构

IMG_43CCEB86C97E-1.JPEG

不一定要套用

组件工具

  • Gin 高性能 go web 框架
  • Go mod

个人想法

我之前学 Java 使用 Springboot 框架的时候从来没有考虑过为什么要分 Map, Service, Controller,只知道它们分别负责什么,而从来没有考虑过这么做的好处或者是有没有可能可以针对项目进行优化,分层结构相关的内容给了我一些启发:比如动态的数据库连接是不是可以在逻辑层和数据层中间加一层从而实现呢?