GoMod | 青训营笔记

189 阅读3分钟

依赖管理

java 里有一个叫 maven 的包管理工具, go 也有一个叫 go mod 的管理工具,可以管理项目引用的第三方包版本、自动识别项目中用到的包、自动下载和管理包。

演进

GOPATH->GO Vendor -> GO Module

GOPATH

  • bin:项目编译的二进制文件
  • pkg:中间产物
  • src:项目源码,直接依赖
  • 弊端:A和B依赖于某一个package的不同版本,无法实现package的多版本控制

Go Vendor

vendor是项目缓存,为了防止开源代码项目被删除无法引用下载,会使用vendor来做缓存管理,它是独立的,可以手动管理引用的包,代码包查找的顺序是向上冒泡

通过每个项目引入一份依赖的副本,解决GoPATH的问题

  • 弊端:无法控制依赖的版本,更新项目有可能出现依赖冲突,导致编译错误

Go Module

  • 使用go mod仓库中可以不用再上传依赖代码包,防止代码仓库过大浪费以及多个项目同时用包时的浪费
  • 可以管理引用包的版本,这一点是gopath(src模式)和vendor做不到的
  • 如果依赖gopath不同项目如果引用了同一个软件包的不同版本,就会造成编译麻烦
  • gopath是go之前的默认策略,每个项目在运行时都要严格放在src目录下,而go mod不用

通过go.mod文件管理依赖包版本

主版本2+模块会在模块路径增加/vN后缀

对于没有go.mod文件并且主版本2+的依赖,会+incompatible

  • incompatible 表示不兼容标识,假如其当前版本为v3.6.0,因为其Module名字未遵循Golang所推荐的风格,即Module名中附带版本信息,我们称这个Module为不规范的Module。 在使用上没有区别,如果是我们自己开发的module,需要从 xxx.com/xxx 变到 xxx.com/xxx/v2
  • indirect 是指间接依赖的包,比如 a module 使用了 b module,但b module的go.mod不完整,或者未启用 go module的话,会把未记录在b的go.mod中又依赖了的包作为间接依赖,放到a的go.mod文件里

原来的包管理方式

  • 在不使用额外的工具的情况下,Go 的依赖包需要手工下载,
  • 第三方包没有版本的概念,如果第三方包的作者做了不兼容升级,会让开发者很难受
  • 协作开发时,需要统一各个开发成员本地$GOPATH/src下的依赖包
  • 引用的包引用了已经转移的包,而作者没改的话,需要自己修改引用。
  • 第三方包和自己的包的源码都在src下,很混乱。对于混合技术栈的项目来说,目录的存放会有一些问题

新的包管理模式解决了以上问题

  • 自动下载依赖包
  • 项目不必放在$GOPATH/src内了
  • 项目内会生成一个go.mod文件,列出包依赖
  • 所以来的第三方包会准确的指定版本号
  • 对于已经转移的包,可以用 replace 申明替换,不需要改代码

依赖分发-回源

Github、SVN

无法保证构建的稳定性、无法保证依赖的可用性,会增加代码托管平台的压力

Go Proxy:缓存一些版本,更可靠、稳定

proxy1.cnproxy2.cn,direct源站

go get

image-20230515113420754

go mod

image-20230515113430993

go mod init:初始化go mod, 生成go.mod文件,后可接参数指定 module 名,上面已经演示过。

go mod download:手动触发下载依赖包到本地cache(默认为$GOPATH/pkg/mod目录)

go mod graph:打印项目的模块依赖结构

go mod tidy :添加缺少的包,且删除无用的包

go mod verify :校验模块是否被篡改过

go mod why:查看为什么需要依赖

go mod vendor :导出项目所有依赖到vendor下

写入go.mod有两种方法:

  • 只要在项目中有 import 并使用或者使用下划线强制占用,然后 go build 时 go module 就会自动下载并添加。
  • go mod tidy

三要素:

配置文件,描述依赖 go.mod

中心仓库管理依赖库 Proxy

本地工具 go get/mod