这是我参与「第三届青训营 -后端场」笔记创作活动的的第2篇笔记
一、Go并发编程
1.并发与并行
并发:指两个或者多个事件在同一时间间隔发生
并行: 指两个或者多个事件在同一时刻发生
并行是在不同实体上的多个事件,并发是在同一实体上的多个事件
线程:用户态,轻量级线程,栈MB级别
协程:内核态,线程跑多个协程,栈KB级别
2.Go语言中的应用
1.Goroutine
goroutine实质是协程,但是它比线程更小,可以认为是轻量级的线程。Go语言中通过通信共享内存的方式比其他语言通过共享内存而通信的方式具有更快速的优点。开启一个goroutine也更加的便捷,使用go关键字即可。例子如下:
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)
}
2.channel
Go语言中通过channel进行共享内存,channel分为有缓存channel和无缓存channel,使用make关键字进行分配内存和初始化。使用channel是并发安全的。例子如下:
func CalSquare() {
src := make(chan int)
dest := make(chan int, 3)
go func() {
defer close(src)
for i := 0; i < 10; i++ {
src <- i
}
}()
go func() {
// 关闭通道
defer close(dest)
for i := range src {
dest <- i * i
}
}()
for i := range dest {
//复杂操作
println(i)
}
}
3.安全Lock
Go语言中通过对Lock的应用来保证并发安全,sync包中已经封装好了互斥锁Mutex
type Mutex struct {
state int32
sema uint32
}
// 接口如下
// 加锁
func (m *Mutex) Lock()
// 释放锁
func (m *Mutex) UnLock()
4.等待数组WaitGroup
WaitGroup也是sync包中的封装结构体
type WaitGroup struct {
noCopy noCopy
state1 [3]uint32
}
// 接口如下
// 添加等待的goroutine数量
func (wg *WaitGroup) Add(delta int)
// 等待数量减1
func (wg *WaitGroup) Done()
// 阻塞等待添加的goroutine执行完毕
func (wg *WaitGroup) Wait()
二、依赖管理
工程项目的完成不可能基于标准库进行编码搭建,要利用第三方库进行快速开发,提高开发效率。这就离不开依赖库的管理。Go语言中的依赖管理经过了是三个阶段:GOPATH阶段、Go Vendor阶段、Go Module阶段。
1.GOPATH阶段
项目代码直接依赖src下的代码,使用go get命令下载最新版本的包到src目录下。弊端是无法实现package的多版本控制。
2.Go Vendor阶段
项目目录下增加vendor文件,所有依赖包副本形式放在$ProjectRoot/vendor。依赖寻址方式:vendor => GOPATH,解决了GOPATH的弊端。但是Go Vendor无法控制依赖的版本,更新项目可能出现依赖冲突,导致编译出错。
3.Go Module阶段
通过go.mod文件管理依赖包版本,通过go get/go mod指令工具管理依赖包。依赖使用时选择最低的兼容版本。通过中心仓库(proxy)管理依赖库。go mod init命令初始化,创建go.mod文件,go mod tidy命令增加需要的依赖,删除不需要的依赖,go mod download命令下载模块到本地缓存。