【青训营】go项目中的依赖管理go module使用| 青训营笔记

129 阅读4分钟

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

在管理小项目的时候,项目需要的依赖基本上都能够根据需求细数出来,但是当一个项目膨胀起来,或者需要有更多的人更多的分支加进来之后,项目的依赖关系就会变得紊乱起来,不同的包如何控制同种依赖的单一性,如何防止不同包版本之间的冲突,如何防止引入冗余的包,这些都是项目中需要考虑的点

事实上,在最开始的go开发中官方并没有提供这样的管理工具,项目的包基本就是由go环境中设置的GOPATH直接对安装的所有包进行管理,缺点很明显,开发人员无法进行一个多版本的控制。所以就出现了go vendor,在开发项目的时候会在项目文件夹中添加一个vendor文件夹,所有的依赖会优先从vendor中获取,没有才会去GOPATH中寻找依赖,这样的处理方式能够进行一个项目的多版本控制,可是还是有不足之处,那就是如何解决依赖冲突的问题,这个时候就出现了接下来要讲的由官方提供的依赖管理工具——Go Module

类似于java中的maven,go在1.16版本开始默认开启go module功能,通过项目下的go.mod文件来管理项目中需要的所有依赖,同时它也提供了一系列相应的命令来进行依赖获取、依赖管理、依赖去重、依赖冲突解决。环境变量中配置的goproxy为中心仓库地址

go.mod

该文件极简化地规定了项目中需要的所有的依赖以及相应的版本,不允许出现冗余的项目依赖,其中会有那么几个模块

  1. module 也就是本项目的名字,项目中的内容都会包含在这个包下
  2. go 规定了项目使用的golang版本号
  3. require 这一部分通常会有两大块,第一块为直接引用,在项目中直接引入的包名,第二块则是间接引用,是由第一部分的直接引用的包中额外包含的依赖
  4. exclude/replace 用于去除或者替换某些依赖,常用于某些依赖的地址失效无法获取到指定的包时

通过以上三个主要模块就描述了项目中所有的依赖信息,同时这里也可以进行一个依赖互斥的处理,如果第一大块中有多个依赖间接引用了不同版本的同一个包,则会根据这几个包的依赖版本自动选择版本最新的依赖。比如说两个依赖同时依赖了一个包的1.3 和 1.4 ,如果这个包已经有1.5了,那也只会选择1.4不会用1.5也不会用1.3

命令

  1. go init 类似于git的初始化,会在当前项目路径下生成一个go.mod文件,初始化当前项目由go module接管包管理,可以在后面添加name来指定当前项目的module的名字

  2. go get 用于从指定url获得需要的依赖,这些依赖会从proxy中获取,下载到GOPATH的pkg的mod下,同时在get的时候也可以指定版本号或者默认下载最新版本的依赖,在保存路径下,文件也会标明版本号,由于这些包基本都在github中,所以除了指定版本之外,还可以额外指定特定的commit或者分支

  3. go mod tidy 用于清理依赖,会自动增加项目中import的依赖,同时删除掉不需要或者未使用过的依赖,这也是符合go的开发风格,极致化地追求简洁

注意点

有关go module的常用命令基本就是以上几点,但是由于go使用依赖的机制,在日常使用中还会出现一些问题

  1. 在GOPATH中会有bin/pkg/src三个文件夹,其中src就是存放各类下载的依赖,bin中会存放项目生成的程序,也就是二进制可运行文件
  2. 在配置go环境的时候,默认GO111MODULE为auto模式,这个时候对于项目如果在gopath/src目录下,项目中的依赖就会在src目录下进行查找,如果项目在gopath/src之外,那对于依赖则是使用go.mod中定义的依赖,所以对于我们自己的项目中,如果一个文件引用了项目中另一个package,就需要import自己项目的module名,因为项目会从go.mod中找对应的依赖,并不能成功定位到自己项目中的另一个package,除非在import中显式地定义了使用的是当前的项目模块名下

以上就是个人对go module的理解,如果有错误或者可以补充的点,可以在评论区中指出