Go语言进阶--关于并发 | 青训营笔记

70 阅读1分钟

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

概要

1、并发编程
2、依赖管理
3、测试
4、实战

一、并发编程

1、协程

协程是轻量级线程,一个线程可以拥有多个协程

相比于线程,协程的优势在于协程的切换发生在用户态,大大减少了切换所带来的开销

使用goroutine创建协程

可以使用go关键字创建协程,如下

for i := 0; i < 5; i++ {
   go func(j int) {
      hello(j)
   }(i)
}

2、协程间通信

使用通信共享内存

channel 是Go语言提供的协程间的通信方式,我们可以使用 channel 在两个或多个 goroutine 之间传递消息。

channel需要使用make函数进行初始化

var chan0 chan int //声明一个channel
chan1 := make(chan int) //声明一个不带缓冲区的channel
chan2 := make(chan int, 3) //声明一个缓冲区大小为3的channel
chan3 := make(chan int, 0) //声明一个不带缓冲区的channel

channel函数有两个参数,第一个参数指传递的值的类型,第二个参数为通道缓冲区的大小,为0和不加参数时,将创建一个不带缓存区的channel

chan1 <- 1 //发送数据
 x := <- chan1 //接收数据

使用不带缓冲区的channel,发送数据后发送方将阻塞,直到接收方接收通道内的数据

使用带有缓冲区的channel时,当缓冲区被填满后,发送方才会阻塞

使用共享内存进行通信

使用锁对临界区加锁以保证并发安全

var lock sync.Mutex //声明一个锁
lock.Lock() //加锁
lock.Unlock //解锁

WaitGroup计数器

WaitGroup对开启的协程计数,每开启一个协程计数器加一,关闭一个协程计数器减一,主协程将阻塞直到计数器归零

var waitgroup sync.WaitGroup //声明一个计数器
waitgroup.Add() //计数器加一
waitgroup.Done() //计数器减一
waitgroup.Wait() //主协程阻塞直到计数器归零

二、依赖管理

使用go modules进行依赖管理

依赖管理三要素:

1、配置文件 ---- go.mod
2、中心仓库 ---- Proxy
3、本地工具 ---- go get/mod

初始化配置文件:

go mod init

执行该命令将会生成go.mod文件

配置中心仓库:

GOPROXY="https://goproxy.cn,direct"

使用go get 获取依赖

go get xxxxx(目标依赖地址)

三、项目测试

测试类型分为三种:回归测试、集成测试、单元测试

1、单元测试

测试文件需要以_test.go结尾

测试函数声明应满足以下格式,否则编译器无法识别

    func TestXxx(*testing.T)

测试初始化逻辑放在TestMain下

启动测试文件命令不再是go run xxx.go而是go test xxx.go

使用覆盖率来衡量项目的测试水准,测试覆盖率应该至少保持在50%以上,尽量全面的覆盖测试分支

Mock机制

为了避免在测试过程中,被测函数中特定的操作对测试代码或测试数据的依赖,可以使用Mock替换掉被依赖的代码或数据

使用Mock函数进行打桩

mock.Patch(target,replacement) //target为目标函数,replacement为替代函数

在代码执行过程中,replacement函数将替代target函数

mock.Unpatch(target) //解除

基准测试

主要测试当前代码的性能以及CPU的损耗

与单元测试类似,测试函数需要满足以下形式

func Benchmarkxxx(*testing.B)

项目实战

项目主要基于gin框架,分为三层结构

数据层:主要实现数据的读取,以及索引的组建
逻辑层:对传入数据的验证以及拼装传出数据的拼装
视图层:对客户端交付数据

需要注意的是,使用c.JSON()函数交付数据时,需要保证结构体内各成员变量的首字母大写

小写字母属于私有变量,无法被包外方法访问,此时客户端无法接收到值!!!