Go并发学习 | 青训营笔记

84 阅读5分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第2篇笔记

Go并发笔记


并发主要是多个任务在单核cpu上以时间片轮转的形式来提高任务处理的效率;并行是利用多个cpu核心多线程来执行任务,可以极大程度的提高处理事务的效率 首先要从 goroutine 协程和常见的线程概念之间的区别说起;

协程:用户态, 可以看做是轻量级的线程, 拥有MB级别的栈空间,可以支持创建上百万的协程 线程:内核态, 线程跑多个协程,线程的栈空间只有KB级别的大小

go语言中通过一个线程调用多个协程来减轻创建多个线程带来的性能开销;协程之间的通信强调用通信来共现内存,而不是通过共享内存来通信;也就是channel 是go语言协程之间的通信方法;

在go 中利用通道机制来实现对数据共享,而不是通过共享数据所在的内存来共享资源;在go 当中存在两种通道的创建机制:

  • make(chan datatype) 无缓冲的通道机制,如果通道内的数据没有被取出,会被阻塞,影响程序性能;
  • make(chan datatyoe, bufsize int) 通过指定一个大于1的缓冲空间给通道,在通道缓冲被占满之前协程之间的通信机制是不会阻塞的,这一点很类似与线程池和队列通信的机制; 但是 go 语言当中仍然保留了利用锁机制来同步的方法:
  • lock sync.Mutex 声明一个异步锁;

这里得说一下临界区的概念,临界区是一种并发过程中存在数据争抢现象的程序逻辑,也就是是对于共享数据的读写相关操作;

子协程和主线程之间的同步,使用sleep方法可以强制主线程在子线程之后执行结束;也可以使用WaitGroup 来开启计数器,一个子协程结束完毕计数器当中记录的运行协程数会减一,计数器会阻塞主协程知道计数器计数为0;

依赖管理

Gopath 通过加外部包安装到src包中: 缺点不能实现包的版本控制

GoVendor 通过在项目路径当中引入 vendor文件,有点类似于Java项目里面的 外部环境库的概念,将依赖的包拷贝一份到vendor 当中,这样每一个不同的项目都有自己的包,在检索依赖包的时候会优先检索本地项目中的 vendor 包,当 vendor 中不存在依赖包的时候再去go path当中检索; 缺点 go Vendor 不能控制依赖的包的版本,这点和Java里面的Maven不一样,更像是只是通过包名来确定依赖关系; go.mod 实现版本控制和依赖管理的机制很像Java中的Maven;

  • 通过配置文件 go.mod 来描述依赖的版本,有点类似于Maven的 pom.xml
  • 通过配置中心仓库来设置依赖库源
  • 本地利用 go get/mod 来

包的版本描述 V1.2.3 这种常见版本好 基于commit提交的时间戳 v1.0.0-20220401081311-c38fb59326b7 版本号,年月日时分秒-哈希编码 对于老版本的包可以在版本号之后加上 +imcompatible 启用兼容模式

利用 go get 来更新删除安装包:

  • go get package @update 安装最近版本的包 默认是
  • go get package @none 删除包
  • go get package @v1.1.2 安装特定版本的包
  • go get package @23dfdd5 安装特定的cmmit
  • go get package @master 安装特定的分支 可以看出最后的三种版本控制形式和git 的版本控制有很大的联系; 利用 go mod 命令来构建项目
  • go mod init 初始化项目类似于git
  • go mod download 拉去模块类似于pull
  • go mod tidy 增加需要的依赖,删除不需要的依赖;

测试

实际工程当中测试时工程开发的重要环节,只有经过严格合理的工程测试才能保证项目的安全和稳定; 测试的环节: 单元测试 -> 集成测试-> 回归测试

  • 单元测试主要时开发阶段对一些函数和模块的功能性测试;通过和期望的测试结果比较来对比结果质量和模块效率;
  • 测试文件以 _test.go 结尾
  • 测试函数以 TestXXX(*testing.T) 来声明
  • 测试数据的初始化逻辑放到 TestMain 函数当中; 单元测试通过计算对模块中代码执行的覆盖率来检验代码的可信度,如果测试的用例涵盖的状态全面,同时测试过程中的代码覆盖率也高,说明测试的可行度越高 在 go test 函数名 --cover 可以输出覆盖率信息;

go 语言单元测试所用的包 monkey: github.com/bouk/monkey mock 打桩方法通过反射机制来替换函数或者模块,来实现对一个输入进行对照实验,防止因为函数对数据的修改或者数据资源发生了不可逆转的变化,导致两个模块的实验输入发生了较大的差异,mock 通过反射打桩和桩函数卸载,原函数回复; 内置的随机数函数性能比较差;可以使用 github.com/bytedance/g…

项目开发的流程


  • 需求分析
  • 代码开发
  • 测试运行

以掘金社区的话题页面为例,演示项目开发的流程

需求用例分析:

  • 浏览消费用户:
    • 话题 id作为唯一标记 标题 内容 创建时间 方便按照时间流来管理
    • 帖子 帖子id 话题id 和话题建立关系 内容 创建时间