Go语言进阶与依赖管理
Go语言进阶
线程 VS 协程
线程: 内核态,切换需要trap系统调用,比较重的操作,栈MB级
协程: 用户态, go语言支持。栈KB级
例子:
func hello(j int) {
fmt.Println("hello ", j)
}
func main() {
// 快速打印hello world
for i:=0 ; i < 5; i++ {
go hello(i);
}
time.Sleep(1*time.Second)
}
协程间通信
提倡通过通信共享内存 —— 需要通道(channel)
不提倡通过共享内存通信(临界区)
channel
make(chan type, size)
初始化时有size的就是有缓冲通道,没有的就是无缓冲通道
简单的生产-消费例子:
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 {
fmt.Println(i);
}
}
并发安全 Lock
例子:
var (
x int64
lock sync.Mutex
)
func addWithLock(){
for i := 0; i < 100 ; i++ {
lock.Lock()
x+=1
lock.Unlock()
}
}
func addWithoutLock(){
for i := 0; i < 100 ; i++ {
x+=1
}
}
WaitGroup
通过waitgroup来实现协程同步
-Add(): 创建协程时调用这个函数,增加wg的值 -Done(): 协程执行完毕时调用这个函数,表示协程退出,减少wg的值 -Wait(): 主线程等待wg的值为0
Go语言依赖管理
GOPATH
-
所有项目都依赖$GOPATH/src下的包
-
go get的时候,都下载到$GOPATH/src
问题: 无法实现package的多版本控制
GO Vendor
- 项目目录下增加vendor文件,所有依赖包以副本的形式放在$ProjectRoot/vendor下
- 解决多个项目需要同一个package依赖冲突
问题:
Go Mod
- 通过go.mod管理依赖包版本
- 通过go get/ go mod指令工具管理依赖包
依赖管理三要素
- 配置文件描述依赖 go.mod
- 中心仓库管理依赖库 Proxy
- 本地工具 go get/mod