Go外部依赖包从vendor,$GOPATH和$GOPATH/pkg/mod查找顺序

vendor

vendor概念最早是由Keith提出,用来存放依赖包。在版本1.5出现。例如gb项目提供了一个名为gsftp的示例项目,它有一个gsftp程序,在标准库之外有三个依赖项。golang.org/x/crypto/ssh, golang.org/x/crypto/ssh/agent和github.com/pkg/sftp。

按vendor概念调整的目录结构如下:

$GOPATH
|	src/
|	|	github.com/constabulary/example-gsftp/
|	|	|	cmd/
|	|	|	|	gsftp/
|	|	|	|	|	main.go
|	|	|	vendor/
|	|	|	|	github.com/pkg/sftp/
|	|	|	|	golang.org/x/crypto/ssh/
|	|	|	|	|	agent/

文件github.com/constabulary/example-gsftp/cmd/gsftp/main.go的引用如下所示,看起来和平时的引用没什么区别。

import (
 ...
 "golang.org/x/crypto/ssh"
 "golang.org/x/crypto/ssh/agent"
 "github.com/pkg/sftp"
)

因为github.com/constabulary/example-gsftp/vendor/golang.org/x/crypto/ssh存在,且正在编译的文件位于以github.com/constabulary/example-gsftp为根的子树中。则导入语句import "golang.org/x/crypto/ssh",编译好像是import "github.com/constabulary/example-gsftp/vendor/golang.org/x/crypto/ssh",只不过这种较长的形式从未写过。

因此github.com/constabulary/example-gsftp中的源代码取决于vendor中有关golang.org/x/crypto/ssh的拷贝副本, 而不是$GOPATH中的其他地方。

vendor的层级搜索

规则是:

从引用文件所在的vendor路径下面搜索,

如果没有找到,那么从上层目录的vendor路径下面搜索,

直到src的vendor路径下面搜索。

modules

Go 1.11版本支持临时环境变量GO111MODULE,通过该环境变量来控制依赖包的管理方式。当GO111MODULE的值为on时,那么就会使用modules功能,这种模式下,$GOPATH不再作为build时导入的角色,依赖包会存放在$GOPATH/pkg/mod目录下。工程中的依赖包也会从此目录下查找。

有关该功能的介绍,可以看Go1.1.1新功能module的介绍及使用。

查找顺序

GO111MODULE=off时,如果一个包在vendor和$GOPATH下都存在,那么使用顺序为:

优先使用vendor目录下面的包,

如果vendor下面没有搜索到,再搜索$GOPATH/src下面的包,

如果$GOPATH下面没有搜索到,那么搜索$GOROOT/src下面的包,

要么完整使用vendor下面的包,要么完整使用$GOPATH下面的包,不会混合使用。

补充:Go 语言编程 — go mod 依赖包管理

使用 go mod

go mod 的子指令

go mod 依赖包管理

Golang 将 Modules(模块)定义为 “源代码交付和版本控制的单元”。

go mod 是 Golang 1.11 版本引入的依赖包管理工具,替换旧的基于 GOPATH 的依赖包管理方式。GOPATH 不再需要包含 src 子目录,使用 go.mod 方式管理的依赖包都被下载到了 $GOPATH/pkg/mod 目录。

有了 go mod 之后,每个项目(源代码目录)就是一个 Module,只要其中包含了 go.mod 文件。go mod 指令和 go.mod 文件用于记录和解析模块之间的依赖性。

go.mod 文件一旦创建后,它的内容将会被 go toolchain(工具链)完全掌控,比如:执行 go get、go build、go mod 等指令时,会自动修改和维护 go.mod 文件。

除了 go.mod 之外,go 指令还维护了一个 go.sum 文件,其中包含特定模块版本内容的加密哈希。go 指令使用 go.sum 文件来确保这些模块的哈希值,以确保项目所依赖的模块不会出现意外更改。

go.mod 和 go.sum 都应该应用于版本控制。 并且 go.sum 不需要手工维护,所以可以不用太关注。

使用 go mod

使用 Go Modules 需要配置 GO111MODULE 环境变量,GO111MODULE 有三个值:off、on 和 auto(默认值):

GO111MODULE=off:关闭 Go Modules,沿用旧版本的 GOPATH 方式,项目的依赖包依旧在 vendor 目录或者 $GOPATH/src 目录下进行查找。

GO111MODULE=on:开启 Go Modules,项目的依赖包记录在 go.mod 文件中。

GO111MODULE=auto:go 指令根据当前目录来决定是否启用 Modules 功能。

当项目处于 GOPATH/src 内,则会使用 GOPATH/src 的依赖包。

当项目处于 GOPATH/src 外,则使用 go.mod 里 require 声明的依赖包。

使用 go.mod 的流程:

在 $GOPATH/src 目录之外创建 Golang 项目。

初始化项目的 go.mod 文件。

$ go mod init <projectNmae>

注意,项目下属的子目录是不需要再次 init 的,整个项目的依赖都会组织在根目录的 go.mod 文件里。

导入外部包:

package main

import (
 "fmt"
 "github.com/gohouse/gorose"
)

func main() {
 fmt.Println("hello world!")
}

运行程序时,会自动下载依赖包并更新 go.mod 文件:

$ go run hello.go
go: finding module for package github.com/gohouse/gorose
go: downloading github.com/gohouse/gorose v1.0.5
go: found github.com/gohouse/gorose in github.com/gohouse/gorose v1.0.5
go: finding module for package github.com/gohouse/converter
go: downloading github.com/BurntSushi/toml v0.3.0
go: downloading github.com/gohouse/converter v0.0.3
go: found github.com/gohouse/converter in github.com/gohouse/converter v0.0.3
go: downloading github.com/go-sql-driver/mysql v1.4.0
# command-line-arguments
./hello.go:5:5: imported and not used: "github.com/gohouse/gorose"

检查 go.mod 文件中自动更新的依赖清单:

module hello

go 1.14

require (
 github.com/gohouse/converter v0.0.3 // indirect
 github.com/gohouse/gorose v1.0.5 // indirect
)

其中 require 是一个关键字,此外还有 module、replace 和 exclude:

module 语句:指定模块的名字(路径)。

require 语句:指定的依赖模块。

replace 语句:可以替换依赖项模块。

exclude 语句:可以忽略依赖项模块。

另外,上述的 v0.0.3 就是依赖包 converter 的版本。如果没有在 go.mod 指定版本,go 指令就会自动下载代码中的依赖的最新版本。否则,go 指令会根据 require 语句的路径和版本进行下载。指定版本时也可以用 latest,表示下载最新的版本。

replace 语句常用于依赖包实际路径变更的场景中,例如:

replace golang.org/x/text => github.com/golang/text latest

如此的,在这种情况下依赖包的维护会变得更简单。

还需要注意 go.mod 中的 module hello 这一条语句,因为当前项目已经不在 $GOPATH/src 内了,所以 module hello 标注了项目 “根” 的路径,以此来作为项目中其他包的根路径。

go mod 的子指令

初始化一个 Module:

go mod init <project_name>

下载项目依赖的 modules 到本地 Cache:

# 在项目目录下执行

go mod download

注:目前所有模块版本数据均缓存在 $GOPATH/pkg/mod 和 $GOPATH/pkg/sum 下。

编辑 go.mod 文件,选项有 -json、-require 和 -exclude:

go mod edit
# e.g.
go mod edit -replace=golang.org/x/crypto@v0.0.0=github.com/golang/crypto@latest

以文本模式打印模块需求图:

go mod graph

删除错误或者不使用的 Modules:

go mod tidy

生成 Vendor 目录:

go mod vendor

验证依赖是否正确:

go mod verify

查找依赖:

go mod why

清理 Modules 缓存:

go clean -modcache

以上为个人经验,希望能给大家一个参考,也希望大家多多支持我们。如有错误或未考虑完全的地方,望不吝赐教。

(0)

相关推荐

  • golang实现ftp实时传输文件的案例

    一.项目简介 本项目主要实现的功能是ftp客户端不断地将xml文件和jpg文件实时地上传到服务器,当然也可以是其他格式的文件.每当ftp客户端取到一个文件之后,将文件上传到服务器后,然后将其删除. 项目实现可配置,如果开发者有类似的需求,只需要修改配置文件就可以使用本项目去完成上传文件的功能. 本项目打日志是按照当天时间来生成日志文件,每天每一种类型的日志只打一个文件. 二.项目结构图片 三.项目代码 config配置中的代码 config.ini [path] xml_path = D:\\d

  • 如何使用go-zero开发线上项目

    前言 ​说在最前面,我是一个外表谦让,内心狂热,外表斯文,内心贪玩的一个普通人.我的职业是程序员,是一个golang语言爱好者,一半是因为golang好用,一半是因为其他语言学不好.我是从phper转为gopher的,写php的时候我认识了互联网软件,写go的时候感觉自己终于在编程. 初见golang ​我大学专业是软件.第一门编程语言是C++,知道了指针,知道了加减乘除,知道了编程去控制软硬件.后来选修了java,被ssh框架戏耍了一个暑假.再后来进入了一个社团技术部,再被html/css/j

  • golang使用 gomodule 在公共测试环境管理go的依赖的实例详解

    背景:调试服务最好的方式就是直接上机实践.对在公司的员工来说,在同一套服务上协同开发比在单独的环境上开发,应该会更有感觉.有问题可以一起发现并解决,也能够一同开发需求. 但是,公司的测试机往往是没办法连外网的,而golang 的大部分工程都需要直接从github 上下载依赖,这就导致 依赖文件需要先提前上传到开发机上.那么当开发机上需要运行多个golang 工程的时候,如何共享这些依赖,减少维护依赖库的工作量呢? 这也是需要大家协作完成的- 最终总结:项目采用 go module + vendo

  • golang-gin-mgo高并发服务器搭建教程

    gin-mgo服务器搭建 该服务器实现简单接收请求并将请求参数封装存储在mongodb数据库中,本文将讲述gin-mgo的使用方法. 项目完整代码地址: https://github.com/wayne-yhp/golang-gin-mgo gin web框架使用介绍 首先获取gin框架依赖 go get gopkg.in/gin-gonic/gin.v1 func main() { server = gin.Default() app.server.GET("/do", IndexR

  • golang实现整型和字节数组之间的转换操作

    我就废话不多说了,大家还是直接看代码吧~ //isSymbol表示有无符号 func BytesToInt(b []byte, isSymbol bool) (int, error){ if isSymbol { return bytesToIntS(b) } return bytesToIntU(b) } //字节数(大端)组转成int(无符号的) func bytesToIntU(b []byte) (int, error) { if len(b) == 3 { b = append([]b

  • go语言实现sftp包上传文件和文件夹到远程服务器操作

    使用go语言的第三方包:github.com/pkg/sftp和golang.org/x/crypto/ssh实现文件和文件夹传输. 1.创建connect方法: func connect(user, password, host string, port int) (*sftp.Client, error) { var ( auth []ssh.AuthMethod addr string clientConfig *ssh.ClientConfig sshClient *ssh.Client

  • Go外部依赖包从vendor,$GOPATH和$GOPATH/pkg/mod查找顺序

    vendor vendor概念最早是由Keith提出,用来存放依赖包.在版本1.5出现.例如gb项目提供了一个名为gsftp的示例项目,它有一个gsftp程序,在标准库之外有三个依赖项.golang.org/x/crypto/ssh, golang.org/x/crypto/ssh/agent和github.com/pkg/sftp. 按vendor概念调整的目录结构如下: $GOPATH | src/ | | github.com/constabulary/example-gsftp/ | |

  • python离线安装外部依赖包的实现

    1.制作requirement.txt pip freeze > requirement.txt 内网安装外部依赖包办法: 例如: 安装pytest包得时候会顺带安装pytest依赖包 离线下载安装包 下载单个离线包 - pip download -d your_offline_packages <package_name> 批量下载离线包 - pip download -d your_offline_packages -r requirements.txt 离线安装 安装单个离线包 -

  • 你应该知道的几类npm依赖包管理详解

    前言 大家都知道在一个Node.js项目中,package.json几乎是一个必须的文件,它的主要作用就是管理项目中所使用到的外部依赖包,同时它也是npm命令的入口文件.下面话不多说了,来一起看看详细的介绍把. npm 目前支持以下几类依赖包管理: dependencies devDependencies peerDependencies optionalDependencies bundledDependencies / bundleDependencies 如果你想使用哪种依赖管理,那么你可

  • golang 如何自动下载所有依赖包

    如何自动下载所有依赖包? 大部分情况下大家下载 Go 项目都是使用go get命令,它除了会下载指定的项目代码,还会去下载这个项目所依赖的所有项目. 但是有的时候我们的项目由于各种原因并不是通过go get下载的,是通过git clone下载的,这样代码下下来就没有依赖包了,没办法编译通过的. 这样的话怎么办呢? go get -d -v ./... -d标志只下载代码包,不执行安装命令: -v打印详细日志和调试日志.这里加上这个标志会把每个下载的包都打印出来: ./...这个表示路径,代表当前

  • Android Studio 引用外部依赖时报错的解决方法

    Android Studio 在引用外部依赖时,发现一直无法引用外部依赖.刚开始以为是墙的问题,尝试修改Gradle配置,未解决问题. 最终发现原来是在Android Sudio安装优化配置时,将Gradle设置为了离线工作模式 解决方法: 只需打开File->Settings->Build,Execution,Deployment->Gradle->取消offline work勾选 总结 以上所述是小编给大家介绍的Android Studio报错Unable to resolve

  • java实现切割wav音频文件的方法详解【附外部jar包下载】

    本文实例讲述了java实现切割wav音频文件的方法.分享给大家供大家参考,具体如下: import it.sauronsoftware.jave.Encoder; import it.sauronsoftware.jave.MultimediaInfo; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import j

  • SpringBoot加载外部依赖过程解析

    这篇文章主要介绍了SpringBoot加载外部依赖过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 背景 公司一个项目的大数据平台进行改造,之前使用Structured Streaming作为实时计算框架,需要替换为替换为Kafka Streams,并使用SpringBoot包装,使其可以纳入微服务体系. 然而由于之前并没有接触过SpringFramework相关技术,并且项目工期较为紧张,因此只好花了2天时间看了看Spring和Spri

  • Spring Boot项目添加外部Jar包以及配置多数据源的完整步骤

    前言 最近项目需要和Oracle数据库进行交互,然后我从Maven中央仓库下载数据库驱动jar包,但怎么都下不下来,我到Oracle官网上一看,我去,居然不让用Maven直接下(大学时候用过Oracle,很久远的事情了0rz),没办法我还是直接下载jar包放到我的项目里面吧.SpringBoot项目引入外部jar包是非常方便的,包含打引入外部jar等操作. 我的做法如下: 首先在src同级目录建一个lib文件夹,将第三方jar包放到这个文件内,比如我将ojdbc6.jar 这个jar包放到这个地

  • go自动下载所有的依赖包go module使用详解

    今天在学习dubbo-go的时候,下载了dubbo-go的example,依赖的包太多了,之前都是手动下载某个依赖的包,现在手动一个一个 go get 那太麻烦了.因为我是搞java的,刚开始用go的时候感觉有点奇怪,go代码所依赖的所有的第三方库都放在GOPATH这个目录下面,这就导致了同一个库只能保存一个版本的代码.如果不同的项目依赖同一个第三方的库的不同版本,应该怎么解决?总不能改包名吧,看了一下 dubbo-samples/golang/的代码 发现了有个 go.mod文件,百度一下 g

  • springboot 打包部署 共享依赖包(分布式开发集中式部署微服务)

    1.此文初衷 平常我们在进行微服务开发完毕后,单个微服务理应部署单个虚机上(docker也可),然后服务集中发布到服务注册中心上,但是有些小的项目,这样做未免太过繁杂增加了部署难度,这里主要讲述的是如何在单机上通过共享jar包的方式来部署多个微服务,解决以上部署难度同时在带宽不够或者网速慢的情况下如何快速的发布部署. 2.部署目录结构   部署目录解答-> 各个微服务与依赖包(lib文件夹下)在同一级目录下,此为图1内容.图二内容展示的是单个微服务内的文件结构,部署配置文件以及所打的jar包,这

随机推荐