这是我参与「第五届青训营 」笔记创作活动的第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.Mutex 和 sync.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