1. 语言进阶
1.1 并发 VS 并行
多线程程序在一个核的cpu上运行
多线程程序在多个核的cpu上运行
Go 可以充分发挥多核优势,高效运行
1.2 Coroutine
协程: 用户态,轻量级线程,栈 KB 级别。 线程: 内核态,线程跑多个协程,栈 MB 级别
快速打印 hello goroutinue 0-4
package main
import (
"fmt"
"time"
)
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)
}
func main() {
HelloGoRoutine()
}
go 语言可以使用
go关键字来快速实现协程可以看到输出并不是有序的,说明协程是并行的
1.2 CSP(Communicating Sequential Processes)
go 语言提倡通过 通过共享内存 而不是通过共享内存而实现通信
1.3 Channel
make(chan 元素类型, [缓冲大小])
- 无缓冲通道
make(chan int) - 有缓冲通道
make(chan int, 2)
- A 协程发送 0~9 个数字
- B 协程计算输入数字的平方
- 主协程输出最后的平方数
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)
}
}
1.4 并发安全 Lock
对变量执行 2000 次 +1 操作,5 个协程并发执行
var (
x int64
lock sync.Mutex
)
func addWithLock() {
for i := 0; i < 2000; i++ {
lock.Lock()
x += 1
lock.Unlock()
}
}
func addWithoutLock() {
for i := 0; i < 2000; i++ {
x += 1
}
}
func Add() {
x = 0
for i := 0; i < 5; i++ {
go addWithoutLock()
}
time.Sleep(time.Second)
println("WithoutLock:", x)
x = 0
for i := 0; i < 5; i++ {
go addWithLock()
}
time.Sleep(time.Second)
println("WithLock:", x)
}
1.5 WaitGroup
计数器: 开启协程+1,执行结束-1,主协程阻塞直到计数器为0
修改之前的打印 hello goroutine 程序
func HelloGoRoutine() {
var wg sync.WaitGroup
wg.Add(5)
for i := 0; i < 5; i++ {
go func(j int) {
defer wg.Done()
hello(j)
}(i)
}
wg.Wait()
//time.Sleep(time.Second)
}
2. 依赖管理
2.1 Go 依赖管理演进
- 不同环境(项目)依赖的版本不同
- 控制依赖库的版本
2.1.1 GOPATH
- 环境变量$GOPATH
- 项目代码直接依赖 src 下的代码
- go get 下载最新版本的包导 src 目录下
GOPATH 弊端
场景 : A 和 B 依赖于某一 package 的不同版本 问题 : 无法实现 package 的多版本控制
2.1.2 Go Vendor
- 目录下新增 vendor 文件,所有依赖包副本形式放在 $ProjectRoot/vendor
- 依赖寻址方式:vendor -> GOPATH
通过每个项目引入一份依赖的副本,解决了多个项目需要同一个 package 依赖的冲突问题。
Go Vendor 弊端
问题 :
- 无法控制依赖版本
- 更新项目又可能出现依赖冲突,导致编译出错
2.1.3 Go Module
- 通过 go.mod 文件管理依赖包版本
- 通过 go get/go mod 指令工具管理依赖包
终极目标: 定义版本规则和管理项目依赖关系
2.2 依赖管理三要素
- 配置文件,描述依赖 go.mod
- 中心仓库管理依赖库 Proxy
- 本地工具 go get/go mod
2.3 依赖配置
2.3.1 依赖配置-go.mod
2.3.2 依赖配置-version
2.3.3 依赖配置-indirect
2.3.4 依赖配置-incompatible
- 主板吧2+模块会在模块路径增加/vN后缀
- 对于没有 go.mod 文件并且主版本2+的依赖,会+incompatible
2.3.5 依赖配置-配置图
2.4 依赖分发
2.4.1 依赖分发-回源
- 无法保证构建稳定性:增加/修改/删除软件版本
- 无法保证依赖可用性:删除软件
- 增加第三方压力:代码托管平台负载问题