golang包管理的古往今来

before GO1.5-GOPATH
在GO1.5之前用GOPATH以及GOROOT这两个环境变量来决定包的位置。
GOROOT就是告知当前go的安装位置,编译的时候从GOROOT去找sdk的system library。
GOPATH的目的是为了告知go,需要代码的时候,去哪里查找。注意这里的代码,包括本项目和引用外部项目的代码。GOPATH可以随着项目的不同而重新设置。 从go 1.8开始,如果GOPATH没有被设置,会有一个默认值,在Unix上为$HOME/go,在Windows上为%USERPROFILE%/go
GOPATH下会有3个目录:src, bin, pkg。
src目录:go编译时查找代码的地方
bin目录:go get、godep这种bin工具的时候,二进制文件下载的目的地
pkg目录:编译生成的lib文件存储的地方。
go允许import不同代码库的代码,例如github.com, k8s.io, golang.org等等;对于需要import的代码,可以使用 go get 命令取下来放到GOPATH对应的目录中去。例如go get github.com/silenceshell/hcache,会下载到$GOPATH/src/github.com/silenceshell/hcache中去,当其他项目在import github.com/silenceshell/hcache的时候也就能找到对应的代码了。
看到这里也就明白了,对于go来说,其实并不care你的代码是内部还是外部的,总之都在GOPATH里,任何import包的路径都是从GOPATH开始的;唯一的区别,就是内部依赖的包是开发者自己写的,外部依赖的包是go get下来的。
存在问题:
不能区分版本,以至于令开发者以最后一项包名作为版本划分
依赖 列表/关系 无法持久化到本地,需要找出所有依赖包然后一个个 go get
只能依赖本地全局仓库($GOPATH/GOROOT),无法将库放置于局部仓库($PROJECT_HOME/vendor)
GO1.5-vendor
GO1.5使用vendor需要手动设置环境变量 GO15VENDOREXPERIMENT=1 ,GO1.6该环境变量默认设为1,在1.7版本时,已去掉该环境变量,默认开启vendor特性。
项目必须在$GOPATH/src目录下
在项目的目录下增加一个 vendor 目录来存放外部的包 , 在这种模式下,会将第三方依赖的源码下载到本地,不同项目下可以有自己不同的vendor。但是这样做又引入了新的问题,因为随着项目的依赖增多,代码库会越来越大,尤其很多带前端资源的项目,几十M到几百M都是很常见的,你的项目可以就依赖它某一点内容,但是却集成了全部资源。
go vendor的管理工具
godep
govendor
glide
go官方wiki给了一个比较全面的对比。
godep更直观,使用者也多一些,一些个人的小项目可以用;glide功能更丰富,更接近maven(例如glide.lock跟maven的pom.xml比较类似,可以指定获取某一个版本),新的项目可以考虑使用glide。
GO1.11-go modules
基于vgo演变而来,是Golang官方的包管理工具。
configure
目前Modules并不是默认启用的,可以通过环境变量GO111MODULE开启或者关闭,它有三个可选值:off、on、auto,默认值是 auto。
off。关闭支持,go 会从GOPATH和vendor文件夹寻找包。
on。开启支持,go 会忽略 GOPATH 和 vendor 文件夹,只根据go.mod下载依赖。
auto。当项目在
$GOPATH/src外,且项目根目录有go.mod文件时,开启模块支持,否则依旧使用GOPATH以及vendor。
go modules使用:
add dependencies
go mod init example.com/hello
go mod命令生成一个go.mod文件,go.mod文件仅出现在模块的根目录中。 子目录中的程序包具有由模块路径以及子目录路径组成的导入路径。 例如,如果我们创建了一个子目录world,则无需(也不希望)在那里运行go mod init。 该软件包将自动被识别为example.com/hello模块的一部分,导入路径为example.com/hello/world。
go命令使用go.mod中列出的特定依赖项模块版本来解析导入。 当遇到未由go.mod中的任何模块提供的包的导入时,go命令将自动使用最新版本查找包含该软件包的模块,并将其添加到go.mod中。 (“最新”定义为最新的标记稳定(非预发行)版本,或者最新的标记预发行版本,或者最新的未标记版本。)在我们的示例中,go test将新的导入rsc.io/quote解析为 rsc.io/quote v1.5.2模块 它还下载了rsc.io/quote使用的两个依赖项,即rsc.io/sampler和golang.org/x/text。 仅直接依赖项记录在go.mod文件中。
go modules 下载的包在 GOPATH/pkg/mod,这就是前面所说的 ‘maven way’;安装的命令仍在 $GOPATH/bin。
除了go.mod之外,go命令还会维护一个名为go.sum的文件,其中包含特定模块版本内容的预期 cryptographic hashes
go命令使用go.sum文件来确保这些模块的将来下载与第一次下载时检索的位相同,以确保您的项目所依赖的模块不会由于恶意,意外或其他原因而意外更改。 应该将go.mod和go.sum都检查到版本控制中。
go list -m all # 列出当前的所有模块以及依赖
update dependencies
版本的表示使用语义版本标签,包括三部分:major;minor;patch。例如v0.2.1,major就是0,minor就是2,patch就是1.
对于minor级别上的升级:
go get golang.org/x/text # 自动下载最新版本
可能会通过,可能出现版本不兼容,
go list -m -versions rsc.io/sampler # 列出此模块可获得的标签版本
go get rsc.io/sampler@v1.3.1 # 下载相应的版本,注意用@再加版本信息,不加版本信息默认@latest
对于major级别上的升级:
Go模块的每个不同的主要版本(v1,v2等)都使用不同的模块路径:从v2开始,该路径必须以主要版本结尾。在示例中,rsc.io/quote的v3不再是rsc.io/quote:而是由模块路径rsc.io/quote/v3标识。此约定称为语义导入版本控制,它为不兼容的程序包(具有不同主要版本的程序包)提供了不同的名称。相反,rsc.io/quote的v1.6.0应该与v1.5.2向后兼容,因此它重用了名称rsc.io/quote。 (在上一节中,rsc.io/sampler v1.99.99应该已经与rsc.io/sampler v1.3.0向后兼容,但是关于模块行为的错误或错误的客户端假设都可能发生。)
go命令允许构建最多包含任何特定模块路径的一个版本,即每个major版本至多:一个rsc.io/quote,一个rsc.io/quote/v2,一个rsc.io/quote/ v3,依此类推。这为模块作者提供了关于可能重复单个模块路径的明确规则:程序无法同时使用rsc.io/quote v1.5.2和rsc.io/quote v1.6.0来构建。同时,允许模块的不同major版本(因为它们具有不同的路径)使模块使用者可以逐步升级到新的主要版本。在此示例中,我们想使用rsc / quote / v3 v3.1.0中的quote.Concurrency,但尚未准备好迁移rsc.io/quote v1.5.2的使用。在大型程序或代码库中,增量迁移的能力尤其重要。
remove unused dependencies
尽管有的模块我们可能不使用了,但是go list -m all还是会显示,以及在go.mod中也会有,不会自动删除。仅在检查模块中的所有软件包以及这些包的所有可能的构建标记组合之后,才能删除依赖项。 普通的build命令不会加载此信息,因此它不能安全地删除依赖项。
go mod tidy # 清除未使用的模块
参考内容:
https://ieevee.com/tech/2017/07/10/go-import.html
http://www.sohu.com/a/330500438_470018
https://blog.golang.org/using-go-modules
https://juejin.im/post/5c6ac37cf265da2de7134242
golang包管理的古往今来的更多相关文章
- Golang 包管理简介
Golang 包管理 在一个项目里,如果想引用本地包,经常会把新手搞的莫名其妙.这里通俗记录一下. 首先先要知道几个默认的规则 必须定义环境变量GOPATH,GOPATH可以定义多个目录 所有项目代码 ...
- Golang包管理工具glide简介
Golang包管理工具glide简介 前言 Golang是一个十分有趣,简洁而有力的开发语言,用来开发并发/并行程序是一件很愉快的事情.在这里我感受到了其中一些好处: 没有少了许多代码格式风格的争论, ...
- golang包管理工具
软件开发中,不可避免的会使用到第三方库,因此包管理工具可以极大的方便开发者管理第三方依赖,避免掉入"依赖地狱". 作为google强大背书的golang语言,golang官方包管理 ...
- Golang 包管理机制
Golang 包管理机制 1. 历史 在go1.11之前, 并没有官方的包管理机制(Godep算个半官方), 主流的包管理机制有: GoVendor Glide Godep 在go1.11之后, 官方 ...
- golang包管理解决之道——go modules初探
golang的包管理是一直是为人诟病之处,从golang1.5引入的vendor机制,到准官方工具dep,目前为止还没一个简便的解决方案. 不过现在go modules随着golang1.11的发布而 ...
- golang包管理的取巧
常见的golang的包管理工具 glide 使用yaml做配置,语义化版本管理,可以设置镜像,下载x系列库,但是x系列库被第三方库依赖时会出现下载失败. dep 亲儿子,语义化版本管理,无法解决墙 v ...
- Glide Golang包管理
Golang的包管理乱得不行,各种工具横空出世,各显神通啊.用了几个下来,发现 Glide 是比较好用的,使用了 vender 来进行管理,多个开发环境的版本不冲突,功能强大,配置文件也足够简单. 初 ...
- golang包管理工具及环境管理工具;如何下载外网的依赖包
简介: golang的包管理工具类似于java的maven.python的pip.js的npm,可以实现依赖包的统一管理:有很多:govendor.godep.glide,挑一个自己喜欢的用吧.mac ...
- window下golang包管理glide使用说明
golang是一门简洁高效的开发 语言,但是包管理一直是一个痛点,如图 : 很多开源项目特别是github.com中的大量应用golang.org和google.golang.org中的源码,且由于被 ...
随机推荐
- JSON《===》JavaBean的相互转换
1.JSON的作用和好处 在JavaWeb项目中前后端直接的交互,接口之间的对接等等,基本离不开JSON. JSON: 全称JavaScript Object Notation(JavaScript ...
- web开发基本概念
一.什么是静态页面,什么是动态页面? 答:静态页面是不需要网络请求就可以看到的页面,保存在本地. 动态页面是需要网络请求才可以看到的页面,保存在服务器. 二.网页的运行环境? 答:浏览器 客户端 三. ...
- MySQL InnoDB 实现高并发原理
MySQL 原理篇 MySQL 索引机制 MySQL 体系结构及存储引擎 MySQL 语句执行过程详解 MySQL 执行计划详解 MySQL InnoDB 缓冲池 MySQL InnoDB 事务 My ...
- java编程思想第四版第十章总结
1. 内部类的特性 他允许你把一些逻辑相关的类组织在一起. 2. 使用.this 如果你需要在内部类中堆外部类进行应用,可以使用外部类的名字后面加.this.下面展示了如何使用 .this packa ...
- ubuntu18+uwsgi+nginx部署django项目
更新系统软件源 sudo apt-get update pip3安装 sudo apt install python3-pip 安装virtualenvwrapper pip3 install vir ...
- 力扣(LeetCode)买卖股票的最佳时机 个人题解
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润. 注意你不能在买入股票前卖出股票. 示例 ...
- 领扣(LeetCode)最长公共前缀 个人题解
编写一个函数来查找字符串数组中的最长公共前缀. 如果不存在公共前缀,返回空字符串 "". 示例 1: 输入: ["flower","flow" ...
- python:类2——有关类和对象的BIF内置函数
1.检查.判断 判断一个类是不是另一个类的子类 issubclass(class, classinfo)如果第一个参数是第二个参数的子类.子子类等,返回true 非严格(自己可以认为是自己的子类): ...
- Qt Framework 问题之 framework/Versions/A:bundle format unrecognized, invalid, or unsuitable
在解决标题提到的问题之后,先来介绍下Qt Framework一些基本知识. 基于QT的Mac端工程,在打包时需要对所有需要嵌入到APP的framework及dylib文件进行手动签名处理. 一.签名处 ...
- Hadoop之HDFS文件系统(二)
HDFS客户端 通过IO流操作HDFS HDFS文件上传 @Test public void putFileToHDFS() throws Exception{ // 1 创建配置信息对象 Confi ...