Go外部依赖包从vendor,$GOPATH和$GOPATH/pkg/mod查找顺序
作者:benben_2015 发布时间:2024-04-28 10:49:59
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
以上为个人经验,希望能给大家一个参考,也希望大家多多支持asp之家。如有错误或未考虑完全的地方,望不吝赐教。
来源:https://blog.csdn.net/benben_2015/article/details/91455497


猜你喜欢
- 搞一个图形化界面还是挺酷的,是吧 安装库什么的应该不用多说了吧。。一般来说会让你把 designer.exe(编辑图形化界面的东西,跟vb差
- 下面是BeforeInitialBind事件过程:<SCRIPT language=vbscript event=
- 1. 引言在某些场景下,我们不仅需要进行实时人脸检测追踪,还要进行再加工;这里进行摄像头实时人脸检测,并对于实时检测的人脸进行初步提取;单个
- 英文原文:http://www.456bereastreet.com/archive/200601/css_3_selectors_expl
- 内容摘要:asp使用最多的就是ACCESS数据库和ms sql server数据库,本文列出了asp连接这两个数据库的方
- 本文是对pandas官方网站上《10Minutes to pandas》的一个简单的翻译,原文在这里。这篇文章是对pandas的一个简单的介
- 问题描述  最近需要给程序新增功能,用于将旧格式的数据转换为新格式,同时删除旧格式的数据(新旧格式的数据
- 使用存储过程,在操作数据库时开启事务,避免并发时同时操作造成数据重复CREATE DEFINER=`root`@`localhost` PR
- 前言:str转换为json格式,前提一定需要保证这个str的格式和json是一致的,即左边最外层是大括号,右边的最外层是大括号。如果不一致,
- Go语言没有继承、构造函数和析构函数等概念,但是它是面向对象的。.net中类型系统分为值类型和引用类型,两种转换需要进行装箱和拆箱,都是继承
- 1.要求数据库存储通讯录,要求按姓名/电话号码查询,查询条件只有一个输入入口,自动识别输入的是姓名还是号码,允许模糊查询。2.实现功能可通过
- 前言GitHub就是一个免费托管开源代码的远程仓库。但是对于某些视源代码如生命的商业公司来说,既不想公开源代码,又舍不得给GitHub交保护
- 三种文件操作比较ioutilbufioos.File当文件较小(KB 级别)时,ioutil > bufio > os。当文件大
- SQL Server连接中三个常见的错误分析 一、"SQL Server 不存在或访问被拒绝&quo
- np.percentilenumpy.percentile(a, q, axis=None, out=None, overwrite_inp
- 一、前奏在谈回调函数之前,先看下下面两段代码:不妨猜测一下代码的结果。function say (value) {  
- 本文实例讲述了Python面向对象类的继承。分享给大家供大家参考,具体如下:一、概述面向对象编程 (OOP) 语言的一个主要功能就是“继承”
- 在内容为主的网站中,搜索框往往是最常用的设计元素之一。从可用性的角度来看,搜索功能是用户有了明确的内容想看的时候最后使用的功能。如果一个网站
- MySQL是一种开放源代码的关系型数据库管理系统(RDBMS),MySQL数据库系统使用最常用的数据库管理语言--结构化查询语言(SQL)进
- Windows 下从源码编译 PaddlePaddle1.环境准备Windows 10 专业版 (64bit)Python 版本 Pytho