二、Go 语言进阶与依赖管理
1、Goroutine
协程:用户态,轻量级线程,栈KB级别
线程:内核态,线程跑多个携程,栈MB级别
//快速打印hello goroutine :0~hello goroutine:4
func hello(i int) {
println("hello goroutine :" + fmt.Sprint(i))
}
func main() {
for i := 0; i < 5; i++ {
//创建一个协程
go func(j int) {
hello(j)
}(i)
}
time.Sleep(time.Second)
}
2、CSP(Communicating Sequential Processes)
提倡通过通信共享内存而不是通过共享内存而实现通信
3、Channel
make(chan 元素类型,[缓冲大小])
- 无缓冲通道 make(chan int)
- 有缓冲通道 make(chan int,3)
func CalSqure() {
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)
}
}
4、并发安全Lock
锁:sync.Mutex
5、WaitGroup
Add(delta int) :计数器+delta
Done():计数器-1
Wait():阻塞直到计数器为0
计数器
开启协程+1:执行结束-1:主协程阻塞直到计数器为0
二、依赖管理
2.1、背景
- 工程项目不可能基于标准库0~1编码搭建
- 管理依赖库
2.1.1 Go依赖管理演进
GOPATH->GO Vendor->Go Module
- 不同环境(项目)依赖的版本不同
- 控制依赖库版本
GOPATH
- 环境变量$GOPATH
- 项目代码直接依赖src下的代码
- go get 下载最新版本的包到src目录下
弊端:无法实现package的多版本控制
GO Vendor
- 项目目录下增加vendor文件,所有依赖包副本形式放在$ProjectRoot/vendor
- 依赖寻址方式:vendor=>GOPATH
通过每个项目引入一份依赖的副本,解决了多个项目需要同一个package的依赖冲突问题
Go Module
- 通过go.mod 文件管理依赖包版本
- 通过go get/go mod 指令工具管理依赖包
终极目标:定义版本规则和管理项目的依赖关系
2.1.2 依赖管理三要素
1、配制文件,描述依赖 :go.mod
2、中心仓库管理依赖库 :Proxy
3、本地工具 : go get/mod
2.1.3 依赖配制-version
语义化版本
${MAJOR}.${MINOR}.${PATCH}
V1.3.0
V2.3.0
基于commit伪版本
vx.0.0-yyyymmddhhmmss- abcdefgh1234
v0.0.0-20220401081311-c38fb59326b7
v1.0.0-20201130134442 -10cb98267c6c
2.1.4依赖分发-回源
- 无法保证构建稳定性
增加/修改/删除软件版本
- 无法保证依赖可用性
删除软件
- 增加第三方压力
代码托管平台负载问题
2.1..5依赖分发-Proxy
稳定可靠
2.1.6依赖分发-变量GOPROXY
GOPROXY="proxy1.cn, proxy2.cn ,direct"
服务站点URL列表," direct"表示源站
Proxy 1 -> Proxy 2 ->Direct
2.1.7 工具- go get
go get example.org/pkg :
- @update :默认
- @none :删除依赖
- @v1.1.2 :tag版本,语义版本
- @23dfdd5 :特定的commit
- @master :分支的最新commit
go.mod :
- init :初始化,创建go.mod文件
- dewnload :下载模块到本地缓存
- tidy : 增加需要的依赖,删除时不需要依赖