首先关于vendor

1 提出问题

我们知道,一个工程稍大一点,通常会依赖各种各样的包。而Go使用统一的GOPATH管理依赖包,且每个包仅保留一个版本。而不同的依赖包由各自的版本工具独立管理,所以当所依赖的包在新版本发生接口变更或删除时,会面临很多问题。

为避免此类问题,我们可能会为不同的工程设置不同的GOPATH,或者更改依赖包路径名称。这样手动维护起来也很头疼。

2 解决问题

Go 1.5引入了vendor文件夹,其对语言使用,go命令没有任何影响。若某个路径下边包含vendor文件夹,则在某处引用包时,会优先搜索vendor文件夹下的包。

在Go 1.5开启该项特性需设置GO15VENDOREXPERIMENT=1,而从Go 1.6开始,该项特性默认开启。

3 使用方式

3.1 vendor搜索方式

vendor包的搜索方式为:自包引用处,从其所在文件夹查询是否有vendor文件夹包含所引用包;若没有,然后从其所在文件夹的上层文件夹寻找是否有vendor文件夹包含所引用包,若没有,则再搜索上层文件夹的上层文件夹...,直至搜索至\(GOPATH/src并搜索完成时止。
例如,如下代码中,`\)GOPATH/src/x/y/z/main.go引用了包"v",则不论vendor/v/v.go`置于src/,src/x/,src/x/y/,src/x/y/z/中任意一个文件夹下,均可以找到。

$ cat $GOPATH/src/x/y/z/main.go

package main

import (
"v"
) func main() {
v.V()
}
$ cat vendor/v/v.go package v import "fmt" func V() {
fmt.Println("I'm a vendor test")
}
$ go run main.go

I'm a vendor test

当vendor存在嵌套时,若不同的vendor文件夹包含相同的包,且该包在某处被引用,寻找策略仍遵循如上规则。即从包引用处起,逐层向上层文件夹搜索,首先找到的包即为所引,也就是从$GOPATH/src来看,哪个vendor包的路径最长,使用哪个。

如下代码中,\(GOPATH/src/x/y/z/main.go所在工程有两个vendor文件夹(分别位于\)GOPATH/src/x/vendor/v/,$GOPATH/src/x/y/z/vendor/v/)包含相同的包"v",目录树为:

$ tree $GOPATH/src

src
└ x
├ vendor
│ └ v
│ └ v.go
└ y
└ z
├ vendor
│ └ v
│ └ v.go
└ main.go
$ cat $GOPATH/src/x/vendor/v/v.go package v import "fmt" func V() {
fmt.Println("I'm a vendor test, My path is x/vendor/v/")
}
$ cat $GOPATH/src/x/y/z/vendor/v/v.go package v import "fmt" func V() {
fmt.Println("I'm a vendor test, My path is x/y/z/vendor/v/")
}

输出为:

$ go run main.go

I'm a vendor test, My path is x/y/z/vendor/v/

可以看到,真正调用的是$GOPATH/src/x/y/z/vendor/v/v.go。

3.2 vendor使用规约

使用vendor时,建议遵循如下两条规约。

  • a) 当欲将某包vendor时,可能想将所有依赖包均vendor;
  • b) 尽量将vendor依赖包结构扁平化,不要vendor套vendor。

    如下示例代码演示vendor扁平化使用。

    main.go位于$GOPATH/src/github.com/olzhy/test下。
package main

import (
"strings"
"sync"
"time" "github.com/z"
"github.com/y"
"golang.org/z"
)
...

$GOPATH/src/github.com/olzhy/test目录树。

├─ main.go
└─ vendor
├─ github.com
│ ├─ x
│ └─ y
└─ golang.org
└─ z

参考资料

[1] https://go.googlesource.com/proposal/+/master/design/25719-go15vendor.md

[2] https://blog.gopheracademy.com/advent-2015/vendor-folder/

[3] https://tonybai.com/2015/07/31/understand-go15-vendor/

转自:

https://leileiluoluo.com

接下来是关于dep

dep 是 golang 项目依赖管理之一,是官方的实验项目,目前更新很频繁处于高速发展期,所以选 dep 作为 golang 的依赖管理器是比较靠谱的。(已知 glide 仅支持不再开发新功能)

目前 dep v0.5.0 release 已经发布,最新的 changelog 显示只支持 golang 1.9+ 以上的版本

golang 最原始的依赖管理是 go get ,执行命令后会拉取代码放入 src 下面,但是它是作为 GOPATH 下全局的依赖,并且 go get 还不能版本控制,以及隔离项目的包依赖在没有依赖管理工具的时候,golang 项目有一种目录结构比较流行如下:

.
└── src
├── demo
│ └── main.go
├── github.com
├── golang.org
└── gopkg.in

这样做的话就是每一个项目一个 GOPATH 则上面的 GOPATH=/xx/xx/src 这样设置后也是可以编译的,且项目依赖都是 src 下的包,与全局的无关联, go get 获取依赖,也必须在项目 GOPATH 下。可以看到这样的目录结构还是有很多缺陷的。特别是 import 包的包目录有时会很奇怪,没有统一的风格,且 ide 或 编辑器支持也不够理想。

所以目前 golang 引入了 vendor 目录作为依赖管理目录,且 ide 或 golang 编辑插件目前都能很好的支持 例如 gogland 索引依赖包时会优先查找项目根目录下的 vendor 目录, vscode 的 go 插件也是。那么目前比较流行的目录结构如下:

.
├── Gopkg.lock
├── Gopkg.toml
├── main.go
└── vendor
├── github.com
│ ├── gin-contrib
│ ├── gin-gonic
│ ├── golang
│ ├── mattn
│ └── ugorji
├── golang.org
│ └── x
└── gopkg.in
├── go-playground
└── yaml.v2

项目目录 $GOPATH/src/projectname/.

Getting Started

install / uninstall

brew install dep
brew uninstall dep
# /usr/local/bin/dep
windows
# 推荐 go get 安装
go get -u github.com/golang/dep/cmd/dep
# $GOPATH/bin/dep.exe
Arch linux
pacman -S dep
# 删除 pacman -R dep
二进制安装
curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
# $GOPATH/bin/dep
# 删除 > rm $GOPATH/bin/dep
源码安装
go get -d -u github.com/golang/dep
cd $(go env GOPATH)/src/github.com/golang/dep
DEP_LATEST=$(git describe --abbrev=0 --tags)
git checkout $DEP_LATEST
go install -ldflags="-X main.version=$DEP_LATEST" ./cmd/dep
git checkout master

推荐安装方式为 各系统的快捷安装,最方便且不容易出错, 如果想使用最新/指定版本,推荐源码安装

初始化项目

推荐使用上述第二种目录结构

mkdir $GOPATH/src/example
cd $GOPATH/src/example
dep init
# 生成 vendor/ 目录下 Gopkg.toml Gopkg.lock

使用流程

Usage
Dep is a tool for managing dependencies for Go projects Usage: "dep [command]" Commands:
init Set up a new Go project, or migrate an existing one
status Report the status of the project's dependencies
ensure Ensure a dependency is safely vendored in the project
prune Pruning is now performed automatically by dep ensure.
version Show the dep version information Examples:
dep init set up a new project
dep ensure install the project's dependencies
dep ensure -update update the locked versions of all dependencies
dep ensure -add github.com/pkg/errors add a dependency to the project Use "dep help [command]" for more information about a command.

获取依赖策略

  • 获取最新TAG的依赖包

    dep ensure -add github.com/gin-gonic/gin

  • 获取指定分支的依赖包

    dep ensure -add github.com/gin-gonic/gin@master

  • 获取指定TAG的依赖包

    dep ensure -add github.com/gin-gonic/gin@V1.2

  • 获取指定TAG以上的依赖包

    dep ensure -add github.com/gin-gonic/gin@^V1.2

  • 获取依赖包的 子包

    dep ensure -add github.com/prometheus/client_golang/prometheus/push

  • 获取两个子包的情况

    dep ensure -add github.com/prometheus/client_golang/prometheus/push github.com/prometheus/client_golang/prometheus/promhttp

  • 获取过程:根据命令先判断本地是否有缓存(缓存地址:$GOPATH/src/dep),存在则直接使用缓存,不存在则,先获取 git 版本/分支/tag 根据命令找到对应的版本下载。

FQAs

  • 当拉取过程中如果出现 timeout 则请自备梯子.
  • 当拉取出现未知的错误,可以先手动删除 缓存 在尝试一次
  • 当出现 *build.NoGoError 错误,可能是 build 时当前依赖包并没有 main 函数,这种情况一般是需要拉取依赖包的子包
  • 当已存在的项目 dep init 会遍历当前项目的依赖包,并下载,所以时间会很久

转自

https://studygolang.com/articles/13990/comment/18351

golang的包管理---vendor/dep等的更多相关文章

  1. Golang学习--包管理工具glide

    上一篇文章中我们已经成功的运行了go的代码,这是我们迈出的最基础的一步. 一个项目通常会依赖很多外部的库,当依赖的库比较多的时候,手工管理就会比较麻烦,这个时候就需要包管理工具出场了,帮你管理好所有依 ...

  2. Go语言包管理工具dep

    什么是dep? dep和go,在一定程度上相当于maven之于Java,composer之于PHP,dep是go语言官方的一个包管理工具. 相比较go get而言,dep可以直接给引入的第三方包一个专 ...

  3. Go包管理工具dep

    dep是一个golang依赖管理工具,需要在Go 1.7及更高的版本中使用. 1. 安装 安装dep工具的方式有很多种,如果是mac电脑的话,只需要如下命令: brew install dep 对于L ...

  4. 拜拜了,GOPATH君!新版本Golang的包管理入门教程

    Go 1.11和1.12实现了对包管理的初步支持,Go的新依赖管理系统使依赖版本信息明确且易于管理.Using Go Modules - The Go Blog 新的包管理模式有什么不同? 作为Go语 ...

  5. nexus 3.17.0 做为golang 的包管理工具

    nexus 3.17.0 新版本对于go 包管理的支持是基于go mod 的,同时我们也需要一个athens server 然后在nexus 中配置proxy 类型的repo 参考配置 来自官方的配置 ...

  6. [golang] Glide 包管理

    一.概述 golang的包管理工具有很多,本篇幅主要介绍glide进行包管理. 二.安装及命令介绍 go get github.com/Masterminds/glide glide create|i ...

  7. [golang] Glide 包管理工具,在windows10 64位系统上的bug修复方案

    bug重现 [ERROR] Unable to export dependencies to vendor directory: Error moving files: exit status 1. ...

  8. golang包管理解决之道——go modules初探

    golang的包管理是一直是为人诟病之处,从golang1.5引入的vendor机制,到准官方工具dep,目前为止还没一个简便的解决方案. 不过现在go modules随着golang1.11的发布而 ...

  9. golang包管理的取巧

    常见的golang的包管理工具 glide 使用yaml做配置,语义化版本管理,可以设置镜像,下载x系列库,但是x系列库被第三方库依赖时会出现下载失败. dep 亲儿子,语义化版本管理,无法解决墙 v ...

随机推荐

  1. 初学python之路-day02

    python,诞生于1989年的圣诞,Guido van Rossum为了打发无聊,因此发明了python,并且开放了其源代码,使得这门语言在随后的几十年的发展的越来越广.现今,2.x版本已经在2.7 ...

  2. img标签里的value获取

    简单描述:在img标签里的value存放了需要用到的值,但是在js中获取的时候,我直接写的就是$("#imgStr").val(),结果发现是空,后来查了一下,才知道,img的va ...

  3. Nhibernate 使用 (二)

    在第一篇中该做的配置基本上已经全部完成,现在直接开始测试 public static ISession NhibClient() { try { // Nhibernate 配置文件的位置 var p ...

  4. [转] 扩展微信小程序框架功能

    通过第三方 JavaScript 库,扩展微信小程序框架功能. 扩展微信小程序框架功能(1)——Promise ES6 对 Promise 有了原生的支持,但微信开发者工具更新版本(0.11.1122 ...

  5. Codeforces 1045E. Ancient civilizations 构造 计算几何 凸包

    原文链接https://www.cnblogs.com/zhouzhendong/p/CF1045E.html 4K码量构造题,CF血腥残暴! 题解 首先,如果所有点颜色相同,那么直接连个菊花搞定. ...

  6. Jboss getshell

     Jboss 的安装需要 JDK 环境 JDK+JBOSS 包  初始环境配置 系统变量名        变量值 PATH                  %JAVA_HOME%\bin:%JAVA ...

  7. JS_ Date对象应用实例

    一.获取日期时间,秒数实时跳动 <!DOCTYPE html> <html lang="en"> <head> <meta charset ...

  8. angular.isElement()

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  9. __x__(7)0905第二天__HTML的发展

    HTML的发展 浏览器各个厂商有不同的标准,一个网页的兼容性非常差. 于是,W3C出来了,作为公益组织定义了HTML标准. 在 1993.6 实现并发布了第一个 HTML. 在 1995.11 开始创 ...

  10. (75)Wangdao.com第十三天_JavaScript 包装对象

    包装对象 所谓“包装对象”,就是分别与数值.字符串.布尔值相对应的Number.String.Boolean三个原生对象 这三个原生对象可以把原始类型的值变成(包装成)对象 var v1 = new ...