第二天笔记总结 | 青训营

115 阅读4分钟

第二天笔记总结 | 青训营

  1. 并行:多线程在多个核的cpu上运行,是实现并发的一种手段
  2. 线程:栈MB级别
  3. 协程:KB级别

我的理解是并发可以提升单个核心的利用率,并行则是利用多个核心完成多项任务,因此并发可以提升并行的效率

goroutine

1.png

  • 快速打印:开启协程打印

  • 调用函数时在函数前加关键字 go

  • 此时是并行乱序输出

CSP

  • 提倡通过通信共享内存
  • 通道连接协程,类似队列,保证收发数据的顺序
  • 利用channal发送特定值到另一个Goroutine

Channel

  • make( chan 元素类型,[缓冲大小])
  1. 无缓冲通道 make(chan int) 同步发送
  2. 有缓冲通道 make(chan int,2) 阻塞发送

这里阻塞的意思应该是预留出等待消费端依次处理数据的时间

A协程功能:生产0-9数字发送到src B协程功能:通过range遍历sre,计算平方发送到有缓冲通道dest

  • 此时scr实现了A、B协程通信
  • 保证了顺序性,是并发安全的
  • 带缓冲的Channel令消费者的消费速度不影响生产者的效率,因为此时不论消费端是否完成,生产者都可以继续执行

并发安全Lock

对变量进行2000次+1操作,5个协程并发执行

  • 加锁:通过Lock()和Unlock()实现,在每次加1之前获取临界区资源,执行后再释放

我认为这里的锁应该是悲观锁,默认数据会被修改

1.png

  • 可见并发安全问题有一定概率影响结果,应控制临界区权限。

WaitGroup

由于无法知道子协程确切时间,无法精确使用sleep进行阻塞

  • 使用waitgroup优化上面代码
  1. 由于有5个协程,因此add(5)
  2. 每个协程执行后,使用Done()对计数器减一,表明此子协程任务结束
  3. 最后通过wait进行阻塞

Go的依赖管理

依赖管理演进

GOPATH -> Go Vendor -> Go Module

GOPATH

  • bin 存放项目编译的二进制文件
  • pkg 项目编译的中间产物,加速编译
  • src 项目源码
弊端
  • 两个project依赖同一pkg的不同版本时,无法同时构建成功,无法实现pkg多版本控制

Go Vendor

  • 项目目录下增加vendor文件夹,所有依赖包副本形式存放在$ProjectRoot/vendor中,优先从这里获取
  • 将不同项目依赖的包放下相应项目vendor下,保证都能构建成功
弊端

无法控制依赖的版本

Go Module

  • 通过go.mod文件管理依赖包版本
  • 通过go get/mod指令工具管理依赖包
  • Proxy 中心仓库管理依赖库

依赖配置

1.png

  • MAJOR-不同版本间可以是代码隔离的
  • MINOR-新增函数或功能,同一MAJOR保持前后兼容
  • PATCH-代码bug的修复

解释了我们在app中见到的版本升级时版本号的命名规则,

indirect关键字

此时indirect标识非直接依赖

关键字incompatible

1.png

依赖配置

依赖C项目不同版本时,选择最低的兼容版本,如使用v1.3和v1.4时,最终编译为v1.4版本

依赖分发

Proxy缓存内容,保证依赖的可靠性,与设置缓存的模式类似

本地工具

go get/mod

测试

单元测试

测试不同函数、模块等,可以保证质量、提升效率,否则定位一个问题的周期会很长

我在跟着思路写代码时出现的错误:单元测试时输出应该是t.Error而不是自己定义输出 并且判断时如果调用t.Error会默认此时为FAIL

assert包

assert.Equal()即可判断是否输出正确

覆盖率

--cover参数,测试到的代码占比

依赖

幂等:重复运行case时结果不变 稳定:单元测试相互隔离,任何时间的函数独立运行

幂等这里我又搜了一下,在分布式系统中,正好可以用到前面学到过的加锁相关知识来实现,防止重复执行

Mock

打桩:A函数替换B函数,此时A为打桩函数 可以为一个函数/方法打桩,不再依赖本地文件

就是用模拟的情况来测试函数是否会出bug

基准测试

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