这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记
依赖管理
Go语言的依赖管理经过不断的改进,目前的 go models 管理方式使用效果的确不错,Go作为想弥补C/C++语言的不足的后起之秀,那么为何在依赖管理上不是一步到位呢?如果深入探究就会发现,最初的解决方式可能只是考虑了C/C++只有 include 的不足和链接阶段的不便,但后来出现的 vender 虽然解决了原来的同一依赖不同版本的问题,但是,实际上是没有完全解决的。
GOPATH
最初的时候,Go语言所有的依赖全部都放在一个GOPATH 的路径下面,据我了解,当初之所以这样做是因为C/C++在进行编译链接的时候经常会因为找不到对应的库出错,所以Go语言设计者可能就把全部的依赖放在一个地方了
存在的问题
主要问题就是如果不同的项目使用了相同的依赖,但是这些依赖的版本是不一样的,但是GOPATH 只能保存一个版本,这个问题就会比较不好解决啦,虽然这只是小部分情况
Vender
基于vendor机制下,在执行 go build 或 go run 命令时,会按照以下顺序去查找包:
- 当前包下的 vendor 目录
- 向上级目录查找,直到找到 src 下的 vendor 目录
- 在 GOROOT 目录下查找
- 在 GOPATH 下面查找依赖包
存在的问题
加入
主要也是对于同一个依赖的不同版本有些问题
GO Module
go mod 是 在 1.11 版本里面新加入的包管理工具或者叫模式,通过在项目文件夹下的一个 go.mod的文件进行包管理的
认识 go.mod文件
module github.com/Moonlight-Zhao/go-project-example //依赖管理基本单元
go 1.16 //标准库版本
require (
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.3.0 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kr/pretty v0.3.0 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/rogpeppe/go-internal v1.8.0 // indirect
github.com/stretchr/testify v1.7.1 // indirect
github.com/ugorji/go v1.2.7 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
go.uber.org/zap v1.21.0
)
对于 require下的,也就是单元依赖,对于单元依赖,每一行就代表一个依赖,包含了路径和 版本的信息
但是其实也有两种方式的
github.com/gin-contrib/sse v0.1.0
上面的这种方式先是指明的依赖的路径,然后指明版本号,版本号分别是大版本,小版本,以及粒度更小的迭代版本号
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
这一种是路径加上版本还有一些其他的额外的信息,依次是一个时间标记,和一个此版本提交的hash值,这一点和 git 有关啦
间接依赖使用 indirect关键字指出,对于下面这个关系
A->B->C
A直接依赖B,A间接依赖C
那么C对应的 go.mod文件可能像下面,后面使用了 indirect关键字
go.uber.org/multierr v1.8.0 // indirect
对于大版本在 2以上的,其路径后面会加上对应 的Vn,如
github.com/go-playground/validator/v10 v10.11.0 // indirect
\
简单做一个总结,就是前两中都在解决以前遇到的一些问题,但是总是有一些不完美的地方,很一个很明显的就是,对于一个项目中不同的依赖又依赖的同一个依赖的不同版本,如何优雅的保存这些不同的依赖版本呢
实际上Go会通过一个算法选择其中兼容的最低版本。(具体这里不表)
go get 工具
默认情况下,直接使用 go get可以下载对应的依赖
go get xxxxxx @update // 主版本的最新一个版本,也是默认选项
go get xxxxxx @none //删除依赖
go get xxxxxx @v1.2.3 //下载特定版本
go get xxxxxx @2cdbf4452 //下载特定的commit版本
go get xxxxxx @dev // 下载特定分支上的版本
go mod init
此命令用来创建一个新的 go.mod 文件
go init v1 //创建v1(也就是上面提到的一个依赖管理单元)
go mod download
下载 go.mod里面的依赖
go mod tidy
增加需要的依赖,删除不需要的依赖
测试
测试是开发过程中保证项目质量的很重要的一项,在设计Go语言当初,其设计者就已经考虑到要原生就支持单元测试,这也的确是非常正确的一个决定,原生支持单元测试和基准测试,带来开箱即用的测试体验,极大的提高了开发人员编码和自测的效率
Go标准库提供了单元测试和基准测试