go mod 与govendor 使用与区别

1,292 阅读2分钟

这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战

go mod 和 govendor 都是 Go 包管理器,类似 Java 工程的 maven

  • 2012年3月 Go 1 发布,此时没有版本的概念
  • 2013年 Golang 团队在 FAQ 中提议开发者保证相同 import path 的兼容性,后来成为一纸空文
  • 2013年10月 Godep
  • 2014年7月 glide
  • 2014年 有人提出 external packages 的概念,在项目的目录下增加一个 vendor 目录来存放外部的包
  • 2015年8月 Go 1.5 实验性质加入 vendor 机制
  • 2015年 有人提出了采用语义化版本的草案
  • 2016年2月 Go 1.6 vendor 机制 默认开启
  • 2016年5月 Go 团队的 Peter Bourgon 建立委员会,讨论依赖管理工具,也就是后面的 dep
  • 2016年8月 Go 1.7: vendor 目录永远启用
  • 2017年1月 Go 团队发布 Dep,作为准官方试验
  • 2018年8月 Go 1.11发布 Modules 作为官方试验
  • 2019年2月 Go 1.12发布 Modules 默认为 auto
  • 2019年9月 Go 1.13 版本默认开启 Go Mod 模式

有这么个故事

故事:失宠的 Vendor 目录

Vendor目录是Golang从1.5版本开始引入的,为项目开发提供了一种离线保存第三方依赖包的方法。但是到了Golang 1.11之后,由于引入了Module功能,在运行go build时,优先引用的是Module依赖包的逻辑,所以Vendor目录就被“无视”了,进而可能发生编译错误, moudle 说还是很想他,于是 提供了 go mod vendor 命令用来生成 vendor 目录。这样能避免一些编译问题,依赖可以先从 vendor 目录进行扫描。

$ go mod help vendor
usage: go mod vendor [-v]

Vendor resets the main module's vendor directory to include all packages needed to build and test all the main module's packages.
It does not include test code for vendored packages.

这句话的意思是: 把 go mod init 后下载的相关依 赖包(Gopath 的 pkg) 目录,拷贝到 vendor 目录。

vendor 目录方式

go vendor 是go 1.5 官方引入管理包依赖的方式

基本思路: 将引用的外部包的源代码放在当前工程的vendor目录下面,go 1.6以后编译go代码会优先从vendor目录先寻找依赖包;找不到再从GOPATH 中寻找

解决的问题

将源码拷贝到当前目录下,这样导包当前工程代码到任意的机器的 ¥GOPATH/src 都可以编译通过,避免项目代码外部依赖过多

未解决的问题

无法精确的引用 外部包进行版本控制,不能指定引用某个特定版本的外部包,只是在开发时将其拷贝过来,但是一旦外部包升级,vendor 下面的包会跟着升级,而且 vendor 下面没有完整的引用包的版本信息, 对包升级带来了无法评估的风险。

什么是 GOROOT 和 GOPATH

  • GOROOT: golang的安装路径,当安装好go之后,默认会安装在/usr/local/go之下。GOROOT的主要作用是标识go的当前安装位置。
  • GOPATH: 存放SDK以外的第三方类库;收藏的可复用的代码,包含三个子目录: -- src : 存放项目源码文件 -- pkg : 编译后的包文件 -- bin :编译后生成的可执行文件

要解决 vendor 目录 未解决的问题,使用 govendor

  • 可以平滑的将现有非 vendor 项目转换成 vendor 项目
govendor add  inport_out_packagename
  • 会生成一个元数据文件,记录工程依赖的外部包,及其版本信息
vendor.json
  • 提高命令查看整个工程的依赖关系
goverdor --list 
goverdor --list -v

govendor

govendor 是一个基于 vendor 机制实现的 Go 包依赖管理命令行工具。与原生 vendor 无侵入性融合,也支持从其他依赖管理工具迁移,可以很方便的实现同一个包在不同项目中不同版本、以及无相互侵入的开发和管理。

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

  • 当前包下的 vendor 目录
  • 向上级目录查找,直到找到 src 下的 vendor 目录
  • 在 GOROOT 目录下查找
  • 在 GOPATH 下面查找依赖包

常用命令

在这里插入图片描述 状态参数 在这里插入图片描述

  1. 安装
go get -u -v github.com/kardianos/govendor
  1. 初始化
cd xxx
govendor init

初始化完成后,项目目录中会生成一个vendor文件夹,包含一个vendor.json文件,json文件中包含了项目所依赖的所有包信息

{
	"comment": "",
	"ignore": "test",
	"package": [],
	"rootPath": "govendor-example"
}

将已被引用且在 $GOPATH 下的所有包复制到 vendor 目录

govendor add +external

仅从 $GOPATH 中复制指定包

govendor add gopkg.in/yaml.v2

列出代码中所有被引用到的包及其状态

govendor list

运行结果

e  github.com/gin-contrib/sse
 e  github.com/gin-gonic/gin
 e  github.com/gin-gonic/gin/binding
 e  github.com/gin-gonic/gin/internal/json
 e  github.com/gin-gonic/gin/render
 e  github.com/golang/protobuf/proto
 e  github.com/mattn/go-isatty
 e  github.com/ugorji/go/codec
 e  gopkg.in/go-playground/validator.v8
 e  gopkg.in/yaml.v2
pl  govendor-example
  m github.com/json-iterator/go
  m golang.org/x/sys/unix

列出一个包被那些包引用

govendor list -v fmt
 s  fmt
    ├──  e  github.com/gin-contrib/sse
    ├──  e  github.com/gin-gonic/gin
    ├──  e  github.com/gin-gonic/gin/render
    ├──  e  github.com/golang/protobuf/proto
    ├──  e  github.com/ugorji/go/codec
    ├──  e  gopkg.in/go-playground/validator.v8
    ├──  e  gopkg.in/yaml.v2
    └── pl  govendor-example

使用建议

  • 使用govendor管理项目并进行项目协作时,我们每次不需要提交整个vendor目录,而只需要提交json文件,十分方便。一个配置文件全部搞定!
  • vendor 目录解决了工程依赖打包的问题,可将依赖与工程一起打包,减少下载依赖的时间。
  • 同一个项目只创建一个govendor目录,且在代码库的一级目录。

缺点

  • 依赖包全部都在vendor目录下,每个项目都有一份,所以每次拉取项目时都会拉一遍依赖。
  • govendor不区分包版本,意味着开发期间拉的依赖的包很可能跟上线后的拉的依赖包版本不一致,很危险。
  • govendor add +e会拉取全部外部包,即使是本项目没有用到的,这样会造成大量的冗余。但是只用govendor add +指定包又很麻烦。

go mod

go module是Go1.11版本之后官方推出的版本管理工具,并且从Go1.13版本开始,go module将是Go语言默认的依赖管理工具。

包不再保存在GOPATH中,而是被下载到了$GOPATH/pkg/mod路径下.

go mod vendor 会将依赖包放到 vendor 目录

在这里插入图片描述

  • go.mod文件记录了项目所有的依赖信息,其结构大致如下:
module github.com/Q1mi/studygo/blogger

go 1.12

require (
	github.com/DeanThompson/ginpprof v0.0.0-20190408063150-3be636683586
	github.com/gin-gonic/gin v1.4.0
	github.com/go-sql-driver/mysql v1.4.1
	github.com/jmoiron/sqlx v1.2.0
	github.com/satori/go.uuid v1.2.0
	google.golang.org/appengine v1.6.1 // indirect
)
  • go.sum是一个构建状态跟踪文件。它会记录当前module所有的顶层和间接依赖,以及这些依赖的校验和,来确保这些模块的将来下载内容与第一次下载的内容相同,但是第一次下载的模块也有可能是非法的(代理服务不可信、模块源被黑等),所以Go 1.13推出GOSUMDB(Go CheckSum Database)用来公证模块的Hash值,从而提供一个可以100%复现的构建过程并对构建对象提供安全性的保证,同时还会保留过去使用的包的版本信息,以便日后可能的版本回退。

go mod

在这里插入图片描述

go mod 与 go vendor 区别

在这里插入图片描述

欢迎关注公众号:程序员财富自由之路