Go 学习笔记/Go语言项目实践 | 青训营笔记

253 阅读4分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记

依赖管理

Go语言的依赖管理经过不断的改进,目前的 go models 管理方式使用效果的确不错,Go作为想弥补C/C++语言的不足的后起之秀,那么为何在依赖管理上不是一步到位呢?如果深入探究就会发现,最初的解决方式可能只是考虑了C/C++只有 include 的不足和链接阶段的不便,但后来出现的 vender 虽然解决了原来的同一依赖不同版本的问题,但是,实际上是没有完全解决的。

GOPATH

最初的时候,Go语言所有的依赖全部都放在一个GOPATH 的路径下面,据我了解,当初之所以这样做是因为C/C++在进行编译链接的时候经常会因为找不到对应的库出错,所以Go语言设计者可能就把全部的依赖放在一个地方了

存在的问题

主要问题就是如果不同的项目使用了相同的依赖,但是这些依赖的版本是不一样的,但是GOPATH 只能保存一个版本,这个问题就会比较不好解决啦,虽然这只是小部分情况

Vender

基于vendor机制下,在执行 go build 或 go run 命令时,会按照以下顺序去查找包:

  1. 当前包下的 vendor 目录
  2. 向上级目录查找,直到找到 src 下的 vendor 目录
  3. 在 GOROOT 目录下查找
  4. 在 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标准库提供了单元测试和基准测试