青训营X豆包MarsCode 技术训练营第二课 | 豆包MarsCode AI 刷题

73 阅读3分钟

Go语言的进阶和依赖管理

1.并发&并行(Go语言就行用并发)

(1)并发:多线程程序在一个核的cpu上运行

(1)并行:多线程程序在多个核的cpu上运行

2.线程&协程

(1)协程:用户态,轻量级线程,栈KB级别

(2)线程:内核态,线程跑多个协程,栈MB计别

例题:
func hello(i int){
println("hello goroutine:"+fmt.Sprint(i))
}

func HelloGoRoutine(){
for i:=0;i<10;i++{
	go func (i int) {
		hello(i)
	}(i)
}
time.Sleep(time.Second)
}

在调用某个函数是,在前面加“go”关键字,就可以创建协程来运行,实现“快速”运行某个函数,例如上述代码中的go func (i int)。上述代码中的time.Sleep(time.Second)主要是为了保证在子协程未完成之前主协程不会退出

3.协程之间的通信——CSP(Communicating Sequential Processes)

Go语言提倡通过通信共享内存而不是通过共享内存实现通信

71f4e87eb9370368bb49567a62053f1.png

4.Channel类型

c57e989a048bebf70dbfe6dd2dcf74d.png

29c85791cc4bb7e82423527eaeba309.png

例如下列代码: func CslSquare(){ 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) }

}

A子协程发送0~9数字,B子协程计算输出数字的平方,主协程输出最后的平方数。上述代码在定义dest通道是,运用的是带缓冲的channel,可以解决消费者和生产者之间“速度”不同的问题。

5.并发安全Lock lock.Lock()和lock.Unlock()相当于“加锁”和“解锁”,提高了安全性,提高并发安全,减少共享内存出错的问题。

(1)计数器:开启协程+1,执行结束-1,主协程阻塞直到计数器为0。

6.依赖管理

(一)分类

(1)GOPATH

简单介绍:

环境变量GOPATH一共包含三部分,分别是:bin、pkg和src。其中,bin是项目编译的二进制文件,pkg是项目编译的中间产物,src是项目源码。项目代码直接以来src下的代码,通过go get下载最新版本的包导src目录下。

弊端:

无法实现package多版本的控制

(2)Go Vendor

项目目录增加vendor文件,所有依赖包副本形式放在¥ProjectRoot/vendor

依赖寻址方式:vendor=>GOPATH

通过每个项目引入一份依赖的副本,解决了多个项目需要同一个package依赖的冲突问题

弊端:

无法控制依赖的版本,更新项目可能出现依赖冲突导致编译出错。

(3)Go Module

通过go.mod文件管理依赖包版本,通过go get/go mod指令工具管理依赖包

最终目标:定义版本规则和关联项目依赖的关系。

(二)三要素

(1)配置文件,描述依赖 go.mod(依赖管理基本单元、原生库、单元依赖)

(2)中心仓库管理依赖库 Proxy

(3)本地工具 go get/mod

(三)依赖配置

(1)version

语义化版本,基于commit伪版本(版本前缀-时间戳-提交commit的12为的哈希码前缀)

(2)indirect

(3)incompatible

(四)依赖图(选择最低的兼容版本)

(五)依赖分发——回源

直接依赖面临的问题:——解决方式:Proxy

(1)无法保证构建稳定性

(2)无法保证依赖的可用性

(3)增加第三方的压力