go包管理
摘自:
http://blueskykong.com/2019/02/18/go-dep-1/
https://www.cnblogs.com/apocelipes/p/10295096.html#vcs-semver
GOPATH和GOROOT
GOROOT的目的就是告知go当前的安装位置,默认go会安装在/usr/local/go下,但也允许自定义安装位置(通过 export GOROOT=$HOME/go1.9.3
指定)。编译的时候从GOROOT去找SDK的system libariry
GOPATH必须要设置,GOPATH告知go,需要代码(包括本项目即内部依赖和引用外部项目的代码即外部依赖)的时候去哪里查找。GOPATH可以随着项目的不同而重新设置。
GOPATH下会有3个目录:src、bin、pkg。
- src目录:go编译时查找代码的地方;按照golang默认约定,go run,go install等命令的当前工作路径(即在此路径下执行上述命令)。
- bin目录:go get这种bin工具的时候,二进制文件下载的目的地; golang编译可执行文件存放路径
- pkg目录:golang编译包时,生成的.a文件存放路径。.a文件是编译过程中生成的,每个package都会生成对应的.a文件,Go在编译的时候先判断package的源码是否有改动,如果没有的话,就不再重新编译.a文件。
内部依赖管理
- 编译时会去
$GOPATH/src/
目录去查找需要的代码
GOPATH来管理外部依赖
go允许import不同代码库的代码,例如github.com, k8s.io, golang.org等等;对于需要import的代码,可以使用 go get 命令取下来放到GOPATH对应的目录中去。例如
go get github.com/globalsign/mgo
(下载和创建项目要保持目录一致,这样才能保证能够正确的引用外部导入和内部导入),会下载到$GOPATH/src/github.com/globalsign/mgo
中去,当其他项目在import github.com/globalsign/mgo
的时候也就能找到对应的代码了。对于go来说,其实并不在意你的代码是内部还是外部的,总之都在GOPATH里,任何import包的路径都是从GOPATH开始的。Go 语言原生包管理的缺陷:
- 依赖 列表/关系 无法持久化到本地,需要找出所有依赖包然后一个个 go get
- 只能依赖本地全局仓库(GOPATH/GOROOT),无法将库放置于局部仓库($PROJECT_HOME/vendor)
vendor
- vendor就是让go编译时,优先从项目源码树根目录下的vendor目录查找代码,如果vendor中有,则不再去GOPATH中去查找。
- 以kube-keepalived-vip为例。该项目会调用k8s.io/kubernetes的库(Client),但如果你用1.5版本的kubernetes代码来编译keepalived,会编译不过。1.5版本中代码有变化,已经没有这个Client了。这就是前面说的依赖GOPATH来解决go import所带来的问题,代码不对上了。
- 使用vendor目录可以把所有依赖的包都拷贝到了vendor目录下,对于需要编译该项目的人来说,只要把代码从github上clone到
$GOPATH/src
以后,就可以进去go build了(注意,必须将kube-keepalived-vip项目拷贝到$GOPATH/src
目录中,否则go会无视vendor目录,仍然去$GOPATH/src
中去找依赖包)。 - 无法精确的引用外部包进行版本控制,不能指定引用某个特定版本的外部包;一旦外部包升级,vendor下的代码不会跟着升级
govendor
该工具将项目依赖的外部包拷贝到项目下的 vendor 目录下,并通过 vendor.json 文件来记录依赖包的版本,方便用户使用相对稳定的依赖。
使用步骤
#安装
go get -u github.com/kardianos/govendor # 进入项目的根目录
# 创建 vendor 文件夹和 vendor.json 文件,此时文件中只有本项目的信息
govendor init # 拷贝GOPATH下的代码到vendor目录中,更新vendor.json
govendor add +包名 # 列出已经存在的依赖包
govendor list # 找出使用的对应包
govendor list -v fmt # 拉取指定版本的包
govendor fetch golang.org/x/net/context@a4bbce9fcae005b22ae5443f6af064d80a6f5a55
govendor fetch golang.org/x/net/context@v1 # Get latest v1.*.* tag or branch.
govendor fetch golang.org/x/net/context@=v1 # Get the tag or branch named "v1".
govendor还可以直接指定依赖包版本来获取包
Modules
go module 是go包的集合,是源代码交换和版本化控制的基本单元
- 「模块根目录」 ( Module root ) : 包含了名为
go.mod
文件的目录,可以存放于文件系统上的任何位置,而不用管GOPATH
路径到底是什么 - 「模块路径」 ( Module path ) : 与模块根目录对应的导入路径的前缀
- 「主模块」( Main module ) : 包行了运行 go 命令的所在目录的模块
GO111MODULE
要使用go module
,首先要设置GO111MODULE=on
。
- 如果设置为
on
,那么无论模块在于何种路径,都会启用模块支持,始终使用 module-aware mode。首先会在$GOPATH/pkg/mod中查找有没有所需要的依赖,没有的直接会进行下载,完全忽略 GOPATH 以及 vendor 目录 - 如果设置为
off
,禁用 go module 功能,go compiler 会始终使用 GOPATH mode,即无论要构建的源码目录是否在 GOPATH 路径下,go compiler 都会在传统的 GOPATH 和 vendor 目录 (仅支持在 GOPATH 目录下的 package) 下搜索目标程序依赖的 go package;如果一个包在vendor和$GOPATH下都存在,查找依赖的顺序:
- 优先使用vendor目录下面的包
- 如果vendor下面没有搜索到,再搜索$GOPATH/src下面的包,
- 如果
$GOPATH
下面没有搜索到,那么搜索$GOROOT/src
下面的包
- 如果没有设置,或设置为
auto
,满足以下任一条件时才使用 module-aware mode:- 当前目录位于 GOPATH/src 之外并且包含 go.mod 文件
- 当前目录位于包含 go.mod 文件的目录下
既有项目
假设你已经有了一个go 项目, 比如在
$GOPATH/github.com/smallnest/rpcx
下, 你可以使用go mod init github.com/smallnest/rpcx
在这个文件夹下(即模块根目录)创建一个空的go.mod
(只有第一行module github.com/smallnest/rpcx
即模块导入名称)。下面是一个简化的go.mod的内容
module my/thing //模块名称 require (//要求的依赖项列表以及版本
one/thing v1.3.2
other/thing v2.5.0 // indirect
...
) exclude (//排除的依赖项,仅在当前模块为主模块时生效
bad/thing v0.7.3
) replace (//替换的依赖项,仅在当前模块为主模块时生效
src/thing 1.0.2 => dst/thing v1.1.0
)
go get ./...
查找依赖,并记录在go.mod
文件中(你还可以指定-tags
,这样可以把tags的依赖都查找到)。执行上面的命令会把
go.mod
的latest
版本换成实际的最新的版本,并且会生成一个go.sum
记录每个依赖库的版本和哈希值,用于验证缓存的依赖项是否满足模块要求
新的项目
你可以在GOPATH
之外创建新的项目。
go mod init packagename
可以创建一个空的go.mod
,然后你可以在其中增加require github.com/smallnest/rpcx latest
依赖,或者像上面一样让go自动发现和维护。
go mod download
可以下载所需要的依赖,但是依赖并不是下载到$GOPATH
中,而是$GOPATH/pkg/mod
中,用来当做缓存,多个项目可以共享缓存的module。
go mod命令
//download 下载依赖的module到本地cache
//edit edit go.mod from tools or scripts (编辑go.mod文件)
例如 go mod edit -require="github.com/chromedp/chromedp@v0.1.0",修改依赖关系使用chromedp 的v0.1.0版本
//tidy 增加丢失的module,去掉未用的module,如在项目的开发过程中, 依赖有变更, 可使用 go mod tidy 来应用这些变更到 go.mod 文件.
//graph print module requirement graph (打印模块依赖图))
//init 在当前文件夹下初始化一个新的module, 创建go.mod文件
//vendor 在项目发布时会要将依赖复制到项目中,会复制modules下载到vendor中, 貌似只会下载你代码中引用的库,而不是go.mod中定义全部的module。
//verify verify dependencies have expected content (校验依赖)
//why explain why packages or modules are needed (解释为什么需要依赖)
//go list -m -json all //依赖详情
集成
go module 功能被集成到 go
命令行工具中,例如,在调用诸如 go build
,go install
,go run
,go test
之类的命令时,将启动相应的操作,如缓存,创建或更新 go.mod
和 go.sum
等
go get 升级
- 运行
go get -u
将会升级到最新的次要版本或者修订版本 - 运行
go get -u=patch
将会升级到最新的修订版本 - 运行
go get package@version
将会升级到指定的版本号version
语义化版本
golang官方推荐的最佳实践叫做semver
,写全了就是Semantic Versioning
(语义化版本)。形如vX.Y.Z
的形式显然比一串hash更直观,x.y.z, z是修订版本号, y是次要版本号,如此一来包的导入路径发生了变化,不同的导入路径意味着不同的包,更具体的规范在这里。
标记版本号的软件发行后,禁止(MUST NOT)改变该版本软件的内容。任何修改都必须(MUST)以新版本发行。
标准的版本号必须(MUST)采用 X.Y.Z 的格式,其中 X、Y 和 Z 为非负的整数,且禁止(MUST NOT)在数字前方补零。X 是主版本号、Y 是次版本号、而 Z 为修订号。每个元素必须(MUST)以数值来递增。例如:1.9.1 -> 1.10.0 -> 1.11.0。
版本格式:主版本号.次版本号.修订号,版本号递增规则如下:
- 主版本号:当你做了不兼容的 API 修改。每当主版本号递增时,次版本号和修订号必须(MUST)归零。
- 次版本号:当你做了向下兼容的功能性新增,每当次版本号递增时,修订号必须(MUST)归零。
- 如果同时依赖是 v1.5.0 和 v1.10.0,最小的兼容版本是 v1.10.0。
- 修订号:当你做了向下兼容的问题修正。这里的修正指的是针对不正确结果而进行的内部修改
- 如果依赖写成 v1.0.5 和 v1.0.10,这两版本是兼容的,则选择最小版本依赖 v1.0.5
go包管理的更多相关文章
- ASP.NET Core 静态文件及JS包管理器(npm, Bower)的使用
在 ASP.NET Core 中添加静态文件 虽然ASP.NET主要大都做着后端的事情,但前端的一些静态文件也是很重要的.在ASP.NET Core中要启用静态文件,需要Microsoft.AspNe ...
- Linux程序包管理之yum及源代码安装
第十六章.Linux程序包管理之yum及源代码安装 目录 yum介绍 yum配置文件 yum的repo配置文件中可用的变量 yum命令的使用 使用光盘作为本地yum仓库 如何创建yum仓库 编译安装的 ...
- Node.js包管理器Yarn的入门介绍与安装
FAST, RELIABLE, AND SECURE DEPENDENCY MANAGEMENT. 就在昨天, Facebook 发布了新的 node.js 包管理器 Yarn 用以替代 npm .咱 ...
- Python黑帽编程1.3 Python运行时与包管理工具
Python黑帽编程1.3 Python运行时与包管理工具 0.1 本系列教程说明 本系列教程,采用的大纲母本为<Understanding Network Hacks Attack and ...
- 你需要知道的包管理器(Package Manager)
最近我花了一点时间关注了在不同系统之中所用到的包管理器(Package Manager) .最开始的时候,我是在使用Linux操作系统时,对这种工具以及它背后的想法深深迷恋住了:这真是自由的软件世界. ...
- 包管理工具Carthage使用
iOS项目中第三方开源库的工具有Cocoapods和Carthage,swift官方出了一个包管理工具SPM(Swift Package Manager). 首先,大体讲一下Cocoapods和Car ...
- RPM包管理命令rpm
RPM包管理器是Linux系统中最早的软件包管理软件之一,也是目前最流行的软件包管理器,许多发行版都使用RPM作为默认的软件包管理软件. RPM软件包名称格式: samba-client-3.0.33 ...
- Node包管理工具
Node包管理工具 只是简单的介绍一些工具的使用,有利于开发过程.除了介绍Node包管理工具,还介绍了前端打包工具,前端模块管理工具 Node包管理工具: --npm --cnpm ...
- godep 包管理工具
godep是解决包依赖的管理工具 安装 go get github.com/tools/godep 成功安装后,在GOPATH的bin目录下会有一个godep可执行的二进制文件,后面执行的命令都是用这 ...
- pycharm快捷键、常用设置、包管理
pycharm快捷键.常用设置.包管理 在PyCharm安装目录 /opt/pycharm-3.4.1/help目录下可以找到ReferenceCard.pdf快捷键英文版说明 or 打开pychar ...
随机推荐
- [RN] React Native 使用 FlatList 和 ScrollView 的下拉刷新问题
React Native 使用 FlatList 和 ScrollView 实现 下拉刷新时,RefreshControl 控件不起作用, 后来经查明,原来 RefreshControl 要加在 Sc ...
- python开发面试问题
python语法以及其他基础部分 可变与不可变类型: 浅拷贝与深拷贝的实现方式.区别:deepcopy如果你来设计,如何实现: __new__() 与 __init__()的区别: 你知道几种设计模式 ...
- 【JZOJ5553】【20190625】谜
题目 给出一个\(2\times n\)个点的二分图的邻接矩阵\(M\) 以及\(m\)个行替换元,\(k\)个列替换元 \(q\)次询问:op u v 表示用第v个行/列替换元去替换矩阵的第u行/列 ...
- js处理事件冒泡(兼容写法)
event = event || window.event; if (event.stopPropagation) { event.stopPropagation(); } else { event. ...
- seqtk 一款快速处理fasta/fastq 文件的小程序
seqtk 的 GitHub 官网 https://github.com/lh3/seqtk 安装 git clone https://github.com/lh3/seqtk.git cd seqt ...
- UDF——已知入口压力和流量计算压降
有时候我们在计算内流,比如管道内的流动时,只知道入口压力和流量,而我们想要计算得到出口的压力,这个应该怎么办呢?当然新版本的Fluent已经自带了流量出口边界,而这里我们采用Fluent的UDF来实现 ...
- 深度学习最全优化方法总结比较及在tensorflow实现
版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/u010899985/article/d ...
- 【深入学习linux】CentOS 7 最小化安装后的注意事项及一些必备组件的安装
转载:https://blog.csdn.net/F_Srion/article/details/54910943 在VM虚拟机中安装CentOS 7 时 有时候顾虑到电脑硬件性能,我们需要最小化安装 ...
- Anaconda更新失败简单解决[CondaHTTPError: HTTP 000 CONNECTION FAILED for url]
问题:conda无法安装更新,报错内容如下:参考链接:conda httperror http none none for url none Anaconda更新失败 conda create -n ...
- Default Activity Not Found解决方法
2018年04月07日 17:22:44 Luckily_Liu 阅读数 13573更多 分类专栏: android 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上 ...