这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天
本堂课重点内容
- 并发事件及其相关处理
- 依赖管理
- 测试
- 完整的项目实践
详细知识点介绍
1. 语言进阶
Goroutine - 协程的概念
首先是并发(图左)与并行(图右)
Go 可以说就是为了高并发设计的
然后是 协成 和 线程
协程由 Go 管理,是更轻量的线程
协程例子
如何 快速 打印 hello goroutine : 0 ~ hello goroutine :4
package concurrence
import (
"fmt"
"time"
)
func hello(i int) {
println("hello goroutine : " + fmt.Sprint(i))
}
func HelloGoRoutine() {
for i := 0; i < 5; i++ {
go func(j int) { // 为了快速,多协程
hello(j)
}(i)
}
time.Sleep(time.Second) // 只是为了保证子协程完成前主协程不退出
}
CSP - 协程间的通信
提倡 通过通信共享内存 而不是共享内存来实现通信
Channel
代码 ./concurrence/channerl.go 为 channel 的例子。因为生产者(产生数字)比消费者(使用数字)效率可能更高,故使用带缓冲区的 channel 保证顺序性(并发安全性)
注 :Go 语言的 defer 语句会将其后面跟随的语句进行延迟处理,在 defer 归属的函数即将返回时,将延迟处理的语句按 defer 的逆序进行执行,也就是说,先被 defer 的语句最后被执行,最后被 defer 的语句,最先被执行
Sync
共享内存时的并发安全
加锁!
WaitGroup
刚刚的例子都用了 sleep 实现暴力堵塞。这是更优雅的实现,,相当于内部开了计时器,阻塞直到计数器为 0
// 刚刚的函数
func HelloGoRoutine() {
for i := 0; i < 5; i++ {
go func(j int) { // 为了快速,多协程
hello(j)
}(i)
}
time.Sleep(time.Second) // 只是为了保证子协程完成前主协程不退出
}
// 使用wg
func ManyGoWait() {
var wg sync.WaitGroup
wg.Add(5) // 在并发环境中完成指定任务的总数
for i := 0; i < 5; i++ {
go func(j int) {
defer wg.Done()
hello(j)
}(i)
}
wg.Wait() // 等着吧你
}
2. 依赖管理
管理方法
简单来说就是我们不想重复造轮子,但是引入不同的包有可能依赖路径不同,也就催生了依赖管理
简单来说:
- GOPATH 没法解决 A 和 B 两项目依赖某一 package 的多个版本的情况
- Go Vendor 每个项目建 package 的副本,但无法控制以来的版本,更新项目有可能出现冲突,导致出错
- 所以有了 Go Module: 定义版本规则和管理项目依赖关系
Go module 其实类似 Java 里的 maven,三要素为:
- 配置文件,描述依赖 go.mod
- 中心仓库管理依赖库 Proxy
- 本地工具 go get/mod
一个还挺神奇的例子:
依赖分发
其实就是依赖去哪里下载、如何下载
直接从分发平台(如 Github)拉取的话,可能不稳定(对方随时增删改版本)、无法保证可用、增加了对第三方平台的压力。为了解决这个问题,有了 Proxy ,它缓存某个版本,实现稳定依赖分发
Go mod 通过 GOPROXY 环境变量配置 Proxy
3. 测试
-
单元测试
- 和 Java 的蛮像的,也有 assert 之类的
- 基本使用可以看这里
- 覆盖率的概念请参看下面的图,意思是前两行被验证过了,最后一个 return false 没有验证,需要再来个函数验证
- 一些 tips:
- 一般覆盖率五六成,较高覆盖率 80%+
- 测试分支相互独立、全面覆盖
- 测试单元力度足够小,函数单一职责
- 需要 幂等(重复测试结果一样),稳定(单元测试相互隔离,在任何时间对任何行运行)
- 数据库和文件的测试不一定那么方便直接,可能有被人修改等问题,可以使用 MOCK 方法,将内存中函数地址替换,不再依赖数据库/文件
- Go 提供了 benchmark 测试框架,可以测试运行时间等
-
集成测试
-
回归测试
项目实践
需求描述如下
- 话题
Topic - 帖子
PostList
从头实现了一个这样的项目(包括测试),还蛮有意思的。觉得值得一记的地方:
- 相比直接遍历,不如全部存到 map 再直接通过索引拿到内容
- 单例模式
- 对于不相互依赖的流程,考虑并行执行提高效率
课后个人总结
真的很干很硬,课后真的得重新运行实现;反过来说也真的学到了很多,很少见到这么完整的 demo 代码