Go语言进阶与依赖管理
一、并发与并行
- 并发:多线程程序在一个核的cpu上运行
- 并行:多线程程序在多个核的cpu上运行
1.Goroutine
协程:用户态,轻量级线程,栈kb级别
线程:内核态,线程跑多个协程,栈mb级别
2.CSP(Communicating Sequential Processes)
提倡通过通信共享内存(通道)而不是通过共享内存(临界区)实现通信
3.Channel
make(chan 元素类型,[缓冲大小])
- 无缓冲通道 make(chan int) 同步
- 有缓冲通道 make(chan int 2)
package main
//A子协程发送o-9数字,B子协程计算输入数字的平方,主协程输出最后的平方数
func main(){
src := make(chan int)
dest := make(chan int,3)
go func(){
//A
defer close(src)
for i := 0;i < 10; i++{
src <- i
}
}()
go func(){
//B
defer close(dest)
for i := range src{
dest <- i * i
}
}()
//M
for i := range dest{
//复杂操作
println(i)
}
}
输出结果
0
1
4
9
16
25
36
49
64
81
4.并发安全Lock
不加锁的话共享内存会引发一些数据安全问题
5.WaitGroup
其实就是维护了一个计数器的实现
开启协程+1.执行结束-1,主协程阻塞直到计数器为0
Add(delta int) 计数器+delta
Done()计数器-1
Wait()阻塞直到计数器为0
二、依赖管理
1.Go 依赖管理演进
GOPATH->Go Vendor -> Go Module
1.GOPATH
- bin 项目编译的二进制文件
- pkg 项目编译的中间产物,加速编译
- src 项目源码
项目代码直接依赖src下的代码,go get 下载最新版本的包到src目录下
弊端:无法实现package的多版本控制
2.Go Vender
- 项目目录下增加vender文件,所有依赖包副本形式放在项目根目录/vender
- 依赖寻址方式:vender->GOPATH
无法控制依赖的版本,更新项目又可能出现依赖冲突,导致编译出错
3.Go Module
- 通过go.mod文件管理依赖包版本
- 通过go get/go mod指令工具管理依赖包
2.依赖管理三要素
- 配置文件,描述依赖 go.mod
- 中心仓库管理依赖库 Proxy
- 本地工具 go get/mod
1.依赖配置-version
语义化版本${MAJOR}.${MINOR}.${PATCH}
major:大版本,可以不兼容
minor:可以是新增了一些功能等,需要在major下做到兼容
patch:代码维护
基于commit伪版本 vx.0.0-yyyymmddhhmmss-abcdefgh1234
语义化版本号+提价的时间戳+提交的hash前缀
2.依赖配置-indirect
间接依赖,如:
A->B,B->C则A->C就是间接依赖,会有 //indirect标识
3.依赖配置-incompatible
- 主版本2+模块会在模块路径增加/vN后缀
- 对于没有go.mod文件并且主版本2+的依赖,会+incompatible
4.依赖配置-依赖图
5.依赖分发-回源
-
无法保证构建稳定性
增加/修改/删除软件版本
-
无法保证依赖可用性
删除软件
-
增加第三方压力
代码托管平台负载问题
6.依赖分发-Proxy
稳定、可靠
7.依赖分发-变量GOPROXY
8.工具-go get
9.工具-go mod