Go语言的依赖管理 | 青训营笔记

30 阅读5分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 2 天。

一        Go语言的并发

1.1    Goroutine协程特点

协程:用户态,轻量级线程,栈MB级别

线程:内核态,线程可以跑多个协程,栈KB级别

1.2    CSP

通信共享内存:协程间资源的共享是通过通信来实现的,优点在于可以避免访问控制以及由此带来的访问权限等问题,对于轻量级的协程很方便

1.3    Channel

引用类型,用make()声明,声明方式如图,第二种方式声明有缓冲区的通道,可以解决很多同步问题

package concurrence

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)
}
}

一共声明了两个通道,其中src用于生产初值的协程和处理数据的协程之间的通信,而dest用于处理数据的协程和打印结果的主线程之间的通信,如此通过协程之间的通信实现了资源的共享

1.4    并发安全Lock

当不采取协程间通信来共享资源,而是通过对公共内存的访问来共享资源时,会出现访问控制的问题,当某一个协程试图对公共资源进行访问时,可能会出现其他协程正在占用公共资源的情况,导致改协程的访问被拒绝,从而导致不出现预期的结果,尤其是该错误并不容易察觉更加重了这一问题

可以简单地使用在访问公共资源前Lock(),以及在结束访问公共资源时Unlock(),来解决此问题。

1.5    WaitGroup

用于解决等待问题

package concurrence



import (

   "fmt"

   "sync"

)



func hello(i int) {

   println("hello world : " + fmt.Sprint(i))

}



func ManyGo() {

   var wg sync.WaitGroup

   for i := 0; i < 5; i++ {

      wg.Add(1)

      go func(j int) {

         defer wg.Done()

         hello(j)

      }(i)

   }

   wg.Wait()

}

使得5个协程全部结束后程序才可终止

二        依赖管理

2.1    依赖管理演化过程

GOPATH:GOPATH是Go中的一个环境变量,用于指定工作空间的位置。它用于存储Go项目的源代码、二进制文件和包对象。Go工具链使用GOPATH环境变量来查找和管理Go项目的依赖项。GOPATH变量的值是一个或多个目录的列表,以冒号(在Linux和macOS上)或分号(在Windows上)分隔。工程本身也将作为一个依赖包,可以被其它 GOPATH/src 目录下的工程引用。由于上述特点,该模式下GO无版本控制,且不能编译工作目录以外的代码

GO Vendor:Go Vendor是一种在引入Go模块之前管理Go项目依赖关系的机制。它允许开发人员在其项目的源代码树中保留依赖项的副本,而不是依赖于全局Go环境。当使用Go Vendor时,开发人员可以将依赖关系的源代码复制到项目中名为Vendor的目录中。Go工具链将在查找全局Go环境之前查找该目录中的依赖项。这允许开发人员控制他们的项目使用的依赖项的确切版本,并确保即使全局Go环境发生变化,他们的项目仍然能够正确地构建。

但是这样做会极大增加代码冗余度,并且该模式下虽然可以记录某一版本依赖包的版本,但是当依赖包所依赖的包发生变动时,没有一个有效的多级反馈机制,使得版本控制失效。

Go Module:Go module 是 Go 1.11 及更高版本中引入的模块管理系统。它提供了对 Go 代码包的版本管理,可以确保项目依赖的代码包的稳定性和可重复性。Go 模块由 go.mod 文件维护,其中记录了项目所依赖的代码包的版本信息。可以使用 go mod 命令管理模块,如添加或删除依赖项、更新依赖项等。这个系统使得包管理更简单,更快速,在解决依赖问题上更稳定。

2.2    依赖管理三要素

1.go.mod:go.mod文件位于Go模块的根目录,它包含以下信息:

 

Module:模块的名称,它也是模块中包的基本导入路径。

Require:当前模块所依赖的模块列表,以及每个模块所需的最小版本。

Exclude:应该从当前模块的依赖树中排除的模块列表。

Replace:应该被替换为不同版本或模块的模块列表。

go:模块兼容的go语言版本。

go命令使用go中的信息。Mod文件来管理模块的依赖关系,包括根据需要下载和更新包。go mod命令也可以用来操作和检查go.mod文件的内容。

总之,go.mod是一个包含Go项目依赖关系信息的文件,Go命令使用它来管理这些依赖关系。

2.Proxy:Go代理是一种服务,充当Go模块客户端和Go模块服务器之间的中介。它可用于缓存和代理模块下载,提供对防火墙后模块的访问,或添加身份验证和加密等安全特性。

3.go mod/get:go mod和go get都是用于管理go项目中的依赖项的命令。

go mod是一系列命令,用于管理go模块,这是在go 1.11中引入的依赖管理系统。它允许添加、删除和更新依赖项,以管理go.mod文件。它还可以用来下载和更新包,以及构建和测试Go项目。

go get用于下载和安装包及其依赖项。它可以用于从远程版本控制系统(如Git和Mercurial)下载包,并将它们安装到GOPATH中。