Go 语言入门指南:并发开发和依赖管理以及单元测试 | 青训营

111 阅读3分钟

Go 语言进阶

1. 并发 VS 并行

并发:指多个线程交替执行,每个线程执行一部分任务,通过调度器在一个CPU核上切换。Go语言中的goroutine是并发的基本单元。

并行:指多个线程同时执行,每个线程在不同的CPU核上执行独立的任务,实现更高效的计算。Go语言通过goroutine实现并行运算。

2. Goroutine

Goroutine是Go语言中的协程,它是一种轻量级的线程,运行在用户态,栈的大小通常在KB级别,相比操作系统的线程(MB级别)更加高效。

在Go语言中,创建goroutine非常简单,使用 go 关键字即可:

3. CSP(Communicating Sequential Processes)

CSP是一种并发模型,Go语言采用了CSP模型。它鼓励通过通信来共享内存,而不是通过共享内存来实现通信。

在Go语言中,Channel是实现CSP模型的重要机制,可以用于在goroutine之间传递数据。

4. Channel

Channel是一种类型安全的通信机制,用于在多个goroutine之间传递数据。可以通过make函数创建Channel,语法为:

// 无缓冲通道
ch := make(chan 数据类型)

// 有缓冲通道
ch := make(chan 数据类型, 缓冲大小)

5. 并发安全

在多个goroutine并发执行时,访问共享的资源可能导致数据竞争和并发安全问题。为了保证并发安全,可以使用互斥锁(sync.Mutex)对共享资源进行加锁。

var lock sync.Mutex

lock.Lock()
// 对共享资源进行读写操作
lock.Unlock()

6. WaitGroup

WaitGroup是Go语言提供的一种等待机制,用于等待一组goroutine执行完成。它通过计数器实现。 计数器: 开启协程:计数器+1, 关闭协程:计数器-1 主进程阻塞直到计数器为0.

var wg sync.WaitGroup

// 启动goroutine时,计数器+1
wg.Add(1)

go func() {
    // goroutine执行的代码
    wg.Done() // 执行完成后,计数器-1
}()

// 主goroutine等待,直到计数器变为0
wg.Wait()

7. 依赖管理

这部分与Java的Maven;Python的pip|Conda类似,都是管理项目依赖工具。

7.1 发展

GOPATH->GOVENDOR->GOMODULE【最后一个是目前应用最广的】 各版本依赖工具具有的问题:

  • Go path:存在多版本依赖冲突问题;
  • Go vendor:添加vendor文件夹管理依赖,但是在多级依赖下,底层依赖依然会出现版本冲突问题。
  • Go module:通过go.mod文件管理依赖包。通过go getgo mod指令实现管理。

8. 测试

8.1 单元测试

单元测试覆盖范围最广,基本是开发人员对函数、接口等内容的基础测试。

在单元测试中,文件名固定,都是在功能文件基础上补充“_test”结尾拼接成新文件。函数结构如下:

func TestXxx(* testing.T)

8.2 Mock测试

可以使用Mock函数【monkey.Patch;monkey.Unpatch】进行测试。为一个函数/方法打桩。

8.3 基准测试

主要针对性能方面。 函数以BenchmarkSelect开头

优化测试性能,可以使用fastrand,高并发场景可能会有一定的性能问题。