并发
- 线程: 内核态, 线程跑多个协程, 栈空间MB级
- 协程: 用户态, 轻量级线程, 栈空间KB级
- channel 通道: make(chan 元素类型, [缓冲大小(>=2为有缓冲通道)])
- lock 并发安全: sync.Mutex定义互斥锁
- WaitGroup 等待组: sync.WaitGroup定义等待组,
Add(delta uint)计数器增加delta, Done()计数器减1, Wait()阻塞直到WaitGroup为0
- 原子函数(atomic):atomic包提供了对数值类型的原子操作,如
atomic.AddInt64()、atomic.LoadInt64()、atomic.StoreInt64()等完成加法、读和写操作
- 互斥锁(sync/mutex):通过
mutex.lock()和mutex.unlock()创建临界区,临界区内的代码同一时刻只能有一个goroutine执行
- 通道可用于共享资源的发送和接收,通过关键字
chan声明,通过make()函数创建
var wg sync.WaitGroup创建信号量
wg.wait()会阻塞调用它的goroutine直到计数器减为0,wg.add()会增加计数器的值,wg.done()会减少计数器的值
- 当通道关闭后,goroutine依旧可以从通道接收数据,但是不能再向通道里发送数据
func (r *Runner) Add(tasks ...func(int)) {
r.tasks = append(r.tasks, tasks...)
}
- 参数列表中的
...表示可以接收任意数量的参数,func(int)表示函数类型,表示接收一个参数为int类型的并且不返回任何值的函数
select用于多个通道的发送和接收操作,select会阻塞纸质任一个case可以执行,如果有default则不会阻塞,没有信号时直接执行default
依赖管理
GOPATH管理模式: 项目代码直接依赖src下代码, go get将最新版本的包加到src下
./bin 项目编译的二进制文件
./pkg 项目编译的中间产物
./src 项目源码
- 缺点: 无法实现pkg的多版本控制
Go Vender管理模式: 在项目目录下增加vender文件夹, 所有依赖包以副本形式存放于$ProjectRoot/vender, 首先vender=>GOPATH
- 当一个项目直接/间接依赖了同一个包的多个版本时, 出现不兼容, 还是由于vender无法控制包的依赖版本
Go Module管理模式: 1.16开始使用, 定义版本规则和项目依赖关系
go.mod: 管理依赖包版本
go get/go mod指令来管理依赖包
- 依赖管理三要素
- 配置文件描述依赖 go.mod
- 中心仓库管理依赖库 Proxy
- 本地工具 go get/mod
- 依赖配置
- version
* 语义化版本
${MAJOR}.${MINOR}.${PATCH}
* 基于commit的伪版本 ${MAJOR}.${MINOR}.${PATCH}-${timestamp}-${hash-checksum}
- indirect 间接依赖
- incompatible 主版本2+模块需要加/vN后缀, 如果没有go.mod文件且主版本为2+的依赖要使用incompatible
- 依赖分发-Proxy: 缓存托管平台分发版本, 保证依赖的稳定可靠
GOPROXY="URL_ADDRESS1, URL_ADDRESS2,..., direct", 从前往后找, direct为源站
- 工具
- go get 下载并安装指定版本的包和依赖包
@update默认方法/@none删除依赖/@vN指定语义版本
- go mod
init 初始化创建go.mod
download 下载模块到本地缓存
tidy 添加缺少的模块, 并删除不需要的模块