Go语言并发、依赖管理和测试 | 青训营笔记

91 阅读4分钟

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

并发

进程(process):程序在操作系统中的一次执行过程,系统进行资源分配和调度的一个独立单位。

线程(thread):操作系统基于进程开启的轻量级进程,是操作系统调度执行的最小单位。

协程(coroutine):由用户自行创建和控制的用户态‘线程’,比线程更轻量级。

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

进程:内核态,线程跑多个协程,栈MB级别

快速打印示例

    for i:=0; i<5; i++{
        go func(j int){    //go声明创建协程
            fmt.Println(j)      
        }(i)
    }
    time.Sleep(time.Second)    //子协程在执行完前,主线程不退出

常见并发模型:

  • 线程&锁模型
  • Actor模型
  • CSP模型
  • Fork&Join模型

Go语言中的并发程序主要是通过基于CSP(communicating sequential processes)的goroutine和channel来实现

CSP(communicating Sequential Processes)协程间通信

Go提倡通过通信共享内存(Channel), 而不是共享内存(临界区)来通信

Channel

Goroutine 是 Go 语言支持并发的核心,一个goroutine会以一个很小的栈开始其生命周期,一般只需要2KB。区别于操作系统线程由系统内核进行调度, goroutine 是由Go运行时(runtime)负责调度。 只需要在函数或方法调用前加上go关键字就可以创建一个 goroutine,如go func1()

go func1()
fmt.Println(1)//一般先执行println

在程序中创建 goroutine 执行函数需要一定的开销,而与此同时 main 函数所在的 goroutine 是继续执行的。 Go 语言中通过sync包为我们提供了一些常用的并发原语。

无缓冲的通道又称为阻塞的通道,只有在有接收方能够接收值的时候才能发送成功,否则会一直处于等待发送的阶段deadlock。 除了创建接受通道,还可以使用有缓冲区的通道。我们可以在使用 make 函数初始化通道时,可以为其指定通道的容量。

依赖管理

godep
最早的时候,Go所依赖的所有的第三方库都放在GOPATH这个目录下面。这就导致了同一个库只能保存一个版本的代码。
为了解决不同的项目依赖同一个第三方的库的不同版本的问题,Go语言从v1.5开始开始引入vendor模式,如果项目目录下有vendor目录,那么go工具链会优先使用vendor内的包进行编译、测试等。
godep是一个通过vender模式实现的Go语言的第三方依赖管理工具,类似的还有由社区维护准官方包管理工具dep。
在项目文件夹上运行go get github.com/tools/godep

go mudule

使用 go module 管理依赖后会在项目根目录下生成两个文件go.mod和go.sum。

go get
在项目中执行go get命令可以下载依赖包,并且还可以指定下载的版本。
1. 运行go get -u将会升级到最新的次要版本或者修订版本(x.y.z, z是修订版本号, y是次要版本号)
2. 运行go get -u=patch将会升级到最新的修订版本
3. 运行go get package@version将会升级到指定的版本号version
如果下载所有依赖可以使用go mod download命令。
整理依赖
我们在代码中删除依赖代码后,相关的依赖库并不会在go.mod文件中自动移除。这种情况下我们可以使用go mod tidy命令更新go.mod中的依赖关系。
go mod edit
格式化
因为我们可以手动修改go.mod文件,所以有些时候需要格式化该文件。Go提供了一下命令:
go mod edit -fmt
添加依赖项
go mod edit -require=golang.org/x/text
移除依赖项
如果只是想修改go.mod文件中的内容,那么可以运行go mod edit -droprequire=package path,比如要在go.mod中移除golang.org/x/text包,可以使用如下命令:
go mod edit -droprequire=golang.org/x/text

项目

既有项目
如果需要对一个已经存在的项目启用go module,可以按照以下步骤操作:
1. 在项目目录下执行go mod init,生成一个go.mod文件。
2. 执行go get,查找并记录当前项目的依赖,同时生成一个go.sum记录每个依赖库的版本和哈希值。
新项目
对于一个新创建的项目,我们可以在项目文件夹下按照以下步骤操作:
1. 执行go mod init 项目名命令,在当前项目文件夹下创建一个go.mod文件。
2. 手动编辑go.mod中的require依赖项或执行go get自动发现、维护依赖。