1、语言进阶
1.并发与并行
| 并发 | 并行 | |
|---|---|---|
| 处理任务 | 一个CPU处理器同时处理多个线程任务 | 多个CPU处理器同时处理多个线程任务 |
| 存在 | 在一个CPU处理器和多个CPU处理器系统中都存在 | 只能在多个CPU处理器系统存在 |
| CPU资源 | 线程之间去抢占CPU资源,轮流使用(时间片) | 线程间不会抢占CPU资源(各做各) |
2.线程与协程
线程从属于进程,是轻量级的进程,处于内核态;协程是一种轻量级线程,从属于线程,处于用户态,即意味着协程的调度完全由用户控制。在Go语言中用的就是协程,这也是Go语言更高效的原因之一。
3.协程间通信
Go语言中提倡通过通信共享内存,而不是通过共享内存实现通信。
Go语言中通道的建立:
chanA := make(chan int)//无缓冲通道
chanB := make(chan int, 3)//有缓冲通道,缓冲区大小为3
4.并发安全锁
Go语言中的互斥锁,位于sync包中的Mutex类型。保证同一时间只有一个协程进入临界区,其他的协程则在等待锁;当互斥锁释放后,等待的协程才可以获取锁进入临界区,多个协程同时等待一个锁时,唤醒的策略是随机的。
var lock sync.Mutex
var x int64
func add(){
for i := 0; i < 2000; i++ {
lock.Lock()//获取锁
x++
lock.Unlock()//释放锁
}
}
当只需要读取一个资源而不涉及资源修改的时候,更推荐读写互斥锁。读写锁在Go语言中使用sync包中的RWMutex类型。
读写锁分为两种:读锁和写锁。当一个协程获取读锁之后,其他的协程如果获取读锁则会继续获取锁,如果是获取写锁就会等待;当一个协程获取写锁之后,其他的协程无论是读锁还是写锁都会等待。
var x int64
var rwlock sync.RWMutex
func write() {
rwlock.Lock() //加写锁
x++
time.Sleep(time.Microsecond * 10)
rwlock.Unlock() //解写锁
}
func read() {
rwlock.RLock() //加读锁
time.Sleep(time.Millisecond)
rwlock.RUnlock() //解读锁
}
5.WaitGroup
Go语言使用sync.WaitGroup来实现并发同步。主要有三个方法:
- wg.Add() 计数器+1;
- wg.Done() 计数器-1;
- wg.Wait() 等到直到计数器变为0;
sync.WaitGroup内部维护着一个计数器,计数器的值可以增加和减少。当启动了N 个并发任务时,就将计数器值增加N。每个任务完成时通过调用Done()方法将计数器减1。通过调用Wait()来等待并发任务执行完,当计数器值为0时,表示所有并发任务已经完成。
var wg sync.WaitGroup
func hello() {
defer wg.Done() //输出Hello Goroutine后计数器-1
fmt.Println("Hello Goroutine!")
}
func main() {
wg.Add(1) //计数器+1
go hello() // 启动另外一个goroutine去执行hello函数
fmt.Println("main goroutine done!")
wg.Wait() //等到计数器为0
}
2、依赖管理
1.Go依赖管理演进历程:GOPATH -> Go Vendor -> Go Module
- GOPATH的管理模式下,如果多个项目依赖同一个库,则依赖该库是同一份代码,所以不同项目不同依赖同一个库的不同版本时,会发生编译错误。
- Vendor是当前项目中的一个目录,存放当前项目依赖的副本,如果当前项目存在Vendor目录,会优先使用该目录下的依赖,如果依赖不存在,会从GOPATH中找;但仍然无法控制依赖的版本,更新项目又可能出现依赖冲突,导致编译错误。
- Go Module通过go.mod文件管理依赖包版本,通过go get/go mod指令工具管理依赖包。
2.依赖管理三要素
- 配置文件,描述依赖 go.mod
- 中心仓库管理依赖库 Proxy
- 本地工具 go get/mod
3.go get/mod的一些常用
go get example.org/pkg +下列后缀
- @update 默认
- @none 删除依赖
- @v1.12 tag版本,语义版本
- @1111ABC 特定的commit
- @master 分的最新commit
go mod + 下列后缀
- init 初始化,创建go.mod文件
- download 下载模块到本地缓存
- tidy 增加需要的依赖,删除不需要的依赖