进一步学习golang | 青训营笔记

90 阅读2分钟

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

语言进阶

并发编程

并发和并行的区别

并发:多线程程序在一个核的CPU上运行

并行:多线程程序在多个核的CPU上运行

Goroutine

协程:用户态,轻量级线程,栈MB级别。

线程:内核态,线程跑多个协程,栈KB级别

实际上是通过并行去打印的输出

CSP 协程之间的通信

提倡通过通信共享内存而不是通过共享内存而实现通信

Channel

make(chan 元素类型,[缓冲大小])

无缓冲通道 make(chan int).--------->同步通道

有缓冲通道 make(chan int,2)--------->通道容量就代表能存储多少元素

有缓冲和无缓冲的区别

无缓冲的与有缓冲channel有着重大差别,那就是一个是同步的 一个是非同步的。

比如

c1:=make(chan int) 无缓冲

c2:=make(chan int,1) 有缓冲

c1<-1

无缓冲: 不仅仅是向 c1 通道放 1,而是一直要等有别的携程 <-c1 接手了这个参数,那么c1<-1才会继续下去,要不然就一直阻塞着。

有缓冲: c2<-1 则不会阻塞,因为缓冲大小是1(其实是缓冲大小为0),只有当放第二个值的时候,第一个还没被人拿走,这时候才会阻塞。

并发安全 Lock

go中的锁Lock

Golang 中的有两种锁,为 sync.Mutexsync.RWMutex

sync.Mutex 互斥锁,只有一种锁:Lock(),它是绝对锁,同一时间只能有一个锁

sync.RWMutex 读写锁,它有两种锁: RLock() 和 Lock(): RLock() 叫读锁。它不是绝对锁,比起互斥锁有着更高的并行性,它允许多个读者同时读取。 Lock() 叫写锁,它是个绝对锁,就是说,如果一旦某人拿到了这个锁,别人就不能再获取此锁了。

什么是临界区

指的是一个访问共用资源(例如:共用设备或是共用存储器)的程序片段,而这些共用资源又无法同时被多个 线程 访问的特性。当有线程进入临界区段时,其他线程或是 进程 必须等待,有一些同步的机制必须在临界区段的进入点与离开点实现,以确保这些共用资源是被互斥获得使用。只能被单一线程访问的设备。

竞态条件:多线程的核心矛盾是“竞态条件”,即多个线程同时读写某个字段。

竞态资源:竞态条件下多线程争抢的是“竞态资源”。

临界区:涉及读写竟态资源的代码片段叫“临界区”。

WaitGroup

之前用sleep来实现暴力的阻塞,但是我们不知道子协程确切的执行时间,所以我们不能很好的确定sleep的时间

go中存在WaitGroup来实现这个条件

sync.WaitGroup拥有一个内部计数器。当计数器等于0时,则Wait()方法会立即返回。 否则它将阻塞执行Wait()方法的goroutine直到计数器等于0时为止。

依赖管理

背景

依赖指的是利用他人已经验证过的开发组建来提高自己的开发效率

Go依赖管理演进

GOPATH----> GO Vendor ---->Go Moudule

GOPATH

弊端:做不到前后版本的兼容

GO Vendor

依赖寻址方式 vendor =>GOPATH

通过每个项目引入一份依赖的副本,解决了多个项目需要同一个package依赖的冲突问题

弊端:无法控制依赖的版本,更新项目又可能出现依赖冲突,导致编译出错

Go Moudule

通过go.mod文件管理依赖包版本

通过go get/go mod指令工具管理依赖包

依赖管理三要素

配置文件,描述依赖 go.mod

中心文件仓库管理依赖库 Proxy

本地工具 go get/mod

测试

单元测试

规则

所有测试文件都是_test.go结尾

func TestXxx(*testing.T)测试函数

初始化逻辑放到TestMain中

对测试质量进行判断

覆盖率

即经过单元测试的代码占总代码的百分比

基准测试

优化代码,需要对当先代码分析

内置的测试框架提供了基准测试能力

项目实战

需求设计

  • 展示话题和回帖列表
  • 暂不考虑前段页面实现,仅仅实现一个本地web存储
  • 话题和回帖数据用文件存储

用例分析

浏览消费用户

用户看页面存在Topic标题和PostList文章内容! 设计topic类和postlist类

组件工具

Gin高性能 go web框架

Go Mod