《快学 Go 语言》第 16 课 —— 包管理 GOPATH 和 Vendor

  • 时间:
  • 浏览:4
  • 来源:uu快3棋牌_uu快3讨论群_规律

细数 Go 语言的历史发展,模块管理经历了有十个 多重要的阶段。第一阶段是通过全局的 GOPATH 来管理所有的第三方包,第二阶段是通过 Vendor 机制将项目的依赖包局部化,第三阶段是 Go 语言的最新功能 Go Module。

go build: 仅编译。将会当前包里有 main 包,就会生成二进制文件。将会这样 main 包,build 指令仅仅用来检查编译不是 上能 通过,编译完成一定会丢弃编译时生成的所有临时包对象。有些 临时包包括自身的包对象以及所有第三方依赖包的包对象。将会指定 -i 参数,会将编译成功的第三方依赖包对象安里装 GOPATH 的 pkg 目录。

模块的标准型态

了解模块型态的最好最好的最好的最好的办法只是看看别人的模块是如可会会写的,这里亲戚亲戚朋友儿来观察一下 mongo 包。使用下面的命令将 redis 的包下载本 GOPATH 目录下



进入到 GOPATH 目录下面的 src 子目录寻找以前下载的 mongo 包,让我发现目录层级和 go get 指令的包路径正好一一对应起来,目录下面还有更深的子目录。

本节亲戚亲戚朋友儿重点讲解前有十个 多阶段,有些 个多阶段要求亲戚亲戚朋友儿编写代码时时需在 GOPATH 下面对应的包路径目录里写。第有十个 多阶段 Go Module 内容较新,也比较繁复时需另起一节单独讲解。

系统包路径

Go 语言有有些内置包,内置包的使用时时需户手工 import 进来。Go 语言的内置包就有将会编译好的「包对象」,使用时编译器不时需进行二次编译。上能 使用下面的命令查看有些 将会编译好的包对象在哪里。



该命令显示出来的后缀名为 .a 的文件只是将会编译好的包对象。



当亲戚亲戚朋友儿导入第三方包时,编译器优先寻找将会编译好的包对象,将会这样包对象,就会去源码目录寻找相应的源码来编译。使用包对象的编译速率单位会明显快于使用源码。

当亲戚亲戚朋友儿使用的第三方包将会比较陈旧,上能 使用 go get -u 指令拉取最新的依赖包。

Go 语言支持使用 . 和 .. 符号相对导入,很久不推荐使用。官方表示相对导入只应该用于本地测试,将会要正式发布一定时需修改为绝对导入。相对导入上能 从不将代码放上去 GOPATH 底下编写,有些会方便本地测试。很久将代码放上去 GOPATH 底下写又能产生多大障碍呢?总之只是不推荐使用相对导入。

Gopkg.lock 是基于当前的 toml 文件配置规则和项目代码来生成依赖的精确版本,它挑选了 vendor 文件夹里要下载的依赖项代码的目标版本。

包名和目录名不一样

Go 语言允许包名和当前的目录名成不一样,在导入包的以前使用的是目录路径,很久在使用的以前应该使用目录下的包名。有些让我看多导入的路径尾部和真正使用时的包名前缀不一样。



为了防止有些 现象,Go 1.6 引入了 vendor 机制。有些 机制非常简单,只是在你当事人项目的目录下增加有十个 多名字为 vendor 子目录,将当事人项目依赖的所有第三方包放上去 vendor 目录里。有十个 多当你导入第三方包的以前,优先去 vendor 目录里找你时需的第三方包,将会这样,再去 GOPATH 全局路径下找。

到目前位置亲戚亲戚朋友儿一直 在编写单文件代码,只能十个 多 main.go 文件。本节亲戚亲戚朋友儿要开始朝完正的项目型态迈进,时需使用 Go 语言的模块管理功能来组织有些的代码文件。

配置文件

dep 管理的项目会有十个 多配置文件,分别是 Godep.toml 和 Godep.lock。Godep.toml 用于配置具体的依赖规则,底下含有项目的具体版本号信息。通过 toml 配置文件,你即上能 使用远程的依赖包(github),也上能 直接使用本地的依赖包(GOPATH)。还上能 为依赖包指定别名,有十个 多就上能 在代码里使用和真实路径不一样的导入路径。当你时需切换依赖包的不同版本时,上能 在 toml 配置文件里修改依赖的版本号,很久通过 dep ensure 指令来更新依赖项。

很不幸,例子含有些 项目将会停止维护了,下面是它的文档中停止维护的声明。



它将会由有十个 多社区项目接手。将会我要使用 mongo 的包,请使用



编写第有十个 多模块

下面亲戚亲戚朋友儿尝试编写第有十个 多模块,有些 模块是有十个 多算法模块,提供有十个 多最好的最好的最好的办法,有十个 多是计算斐波那契数,有十个 多用来计算阶乘。亲戚亲戚朋友儿要将有些 包放上去 github.com 上,时需读者在 github.com 上申请当事人的账户,很久创建当事人的项目叫青 mathy。我的 github id 是 pyloque,于是有些 项目的包名只是 github.com/pyloque/mathy。第一步在 GOPATH 里创建有些 包目录



好,现在亲戚亲戚朋友儿进入了包的目录下,开始编写代码吧,首先创建 mathy.go 文件,将下面的代码贴进去



现在有些 包的功能都齐全了,下面来编写 main 函数使用它。亲戚亲戚朋友儿上能 去其它的任意空目录下编写下面的 main.go 文件,很久不上能 在当前目录编写,将会同有十个 多目录只能有同有十个 多包名。比如亲戚亲戚朋友儿在 mathy 目录下面创建有十个 多子目录 cmd,将下面的代码放上去 cmd 目录下的 main.go 文件里。执行 go run cmd/main.go 运行观察结果



现在将代码提交到 github.com 上去吧,你最好将会比较熟悉 git 指令

dep status

显示当前项目的依赖情形。

dep init

该指令用于初始化当前的项目,它会静态分析当前的项目代码(如有有语句),生成 Godep.toml 和 Godep.lock 依赖配置文件,将依赖的项目代码下载到当前项目的 vendor 文件夹底下。它会根据一定的策略来挑选最新的依赖包版本。将会自动策略生成的版本号就有了你很久的,上能 再修改配置文件执行 dep ensure 来切换其它版本。

匿名导入

Go 语言还支持匿名导入,只是说你导入了某个第三方包,很久不时需显示使用它,这时就上能 使用匿名导入。有些 以前时需导入某个包而不使用呢?这是将会 Go 语言的代码文件中上能 位于有十个 多特殊的 init() 函数,它会在包文件第一次被导入的以前运行。



当亲戚亲戚朋友儿使用数据库驱动的以前就会一直 遇到匿名导入,第三方驱动包会在 init() 函数中将当前驱动注册到全局的驱动列表中,有十个 多通过特定的 URI 就上能 识别并找到相应的驱动来使用。

Go 语言这样内置 vendor 包管理工具,它时需第三方工具的支持。有十个 多的工具有些,目前最流行的要数 golang/dep 项目了,它差有些就被官方收纳为内置工具了,很可惜!上图是它的 Logo,图中叠起来的箱子只是 dep 正在管理的各种第三方依赖包。使用它以前亲戚亲戚朋友儿时需将 dep 工具安里装 GOPATH 下面



共同时需将 ~/go/bin 目录加入到环境变量 PATH 中,将会 dep 可执行文件默认会安里装 ~/go/bin 中。很久令人意外的是 dep 居然表示只能直接防止「钻石型」依赖,这我要感受到了它的危机,在 dep 中依赖包是扁平化的,vendor 不允许嵌套。将会一直 出現了版本冲突,时需使用有本身特殊手段来防止。

全局管理 GOPATH

Go 语言的 GOPATH 路径下存放了全局的第三方依赖包,当亲戚亲戚朋友儿在代码底下 import 某个第三方包时,编译器一定会到 GOPATH 路径下面来寻找。GOPATH 目录上能 指定多个位置,不过用户一般很少有十个 多做。将会你没村里人 工指定 GOPATH 环境变量,编译器会默认将 GOPATH 指向的路径设定为 ~/go 目录。用户上能 使用下面的命令看看当事人的 GOPATH 指向哪里



GOPATH 下有十个 多重要的子目录,分别是 src、pkg 和 bin 目录。src 目录存放第三方包的源代码,pkg 目录存放编译好的第三方包对象,bin 存放第三方包提供的二进制可执行文件。



很久每个第三方项目一定会有当事人的 vendor 子目录,这样递归下去,上能 想象,有十个 多大型项目将会有一颗深会的依赖树。不过实际上这颗依赖数没你想象的这样深,将会 Go 的第三方开源包普遍比较轻量级,依赖就有有些。毕竟 Go 语言将会将有些互联网常用的工具包都内置了。

无名导入

Go 语言还支持有本身罕见的导入语法上能 将其它包的所有类型变量都导入到当前的文件中,在使用相关类型变量时上能 省去包名前缀。

为有些 json-iterator 会使用有十个 多奇怪的包路径呢,将会它要支持多种语言的,直接将最后的目录名改成语言的名称更加易于辨识。

go get:下载代码、编译和安装。安装内容包括包对象和可执行文件,很久不包括依赖包。

使用 vendor 有十个 多限制,那就有了你只能将 vendor 底下依赖的类型暴露到外面去,vendor 底下的依赖包提供的功能仅限于当前项目使用,这只是 vendor 的「隔离沙箱」。正是将会有些 沙箱才使得项目上能能 位于将会依赖传递原因 的同有十个 多依赖包的多个版本。共同这也原因 项目里将会位于多份同有十个 多依赖包,即使它们是同有十个 多版本。比如你的包在 vendor 里引入了某个第三方包 A,很久别人的项目在 vendor 里引入你的包,共同它也引入第三方包 A。这就会原因 生成的二进制文件变大,也会原因 运行时内存变大,不过只是多担心,这点代价对于服务端系统守护进程来说基本上能 忽略不计。

go install:先编译,再安装。将编译成的包对象安里装 GOPATH 的 pkg 目录中,将编译成的可执行文件安里装 GOPATH 的 bin 目录中。将会指定 -i 参数,一定会安装编译成功的第三方依赖包对象。

局部管理 Vendor

当亲戚亲戚朋友儿在本地要开发多个项目时,将会不同的项目时需依赖某个第三方包的不同版本,这以前仅仅通过全局的 GOPATH 来存放第三方包是无解的。防止最好的最好的最好的办法有十个 多,那只是时需在不同的项目里设置不同的 GOPATH 变量来防止冲突现象。很久这还是只能防止有十个 多重要的现象,那只是当亲戚亲戚朋友儿的项目依赖了有十个 多第三方包,有些 个多第三方包又共同依赖了有十个 多包的有十个 多不同版本,这以前就会再次位于冲突。有些 多版本依赖有十个 多专业的名称叫「钻石型」依赖。

让我发现刚才删掉的 mathy 目录又一直 出現了,将会 go get 指令会自动去 github.com 网站上拉取你刚才提交的项目代码。

打开你的 github 项目页看一看你以前提交的成果吧



有些 项目提交到了 github.com 原因 全球的人都上能 使用你的代码了,前提是亲戚亲戚朋友儿很久使用。

现在让我将本地的 mathy 文件夹删除,很久执行一下 go get

dep ensure -update

更新 Godep.lock 文件中的所有依赖项到最新版本。上能 增加 一到多个包名参数,指定更新特定的依赖包。将会 toml 配置文件限定了依赖包的版本范围,这样更新时需遵守 toml 规则的版本限制。

Dep 在使用起来比较简单,很久其组织组织结构实现上是有十个 多比较繁复的工具,鉴于篇幅限制,本节就不再继续深入讲解 Dep 了,以前有空再单独开启一篇来深入探讨吧。我甚至难能可贵理解 Dep 将会变得这样这样必要,将会它将会被 Go 语言官方抛妻弃子了,取而代之的防止方案是 Go Module。

很久有些 用法很少见,很久非常不推荐使用,读者上能 当着没看见完正问你。

Dep

dep ensure

该指令会下载代码里用到的新依赖项、移除当前项目代码里不使用的依赖项。确保当前的依赖包代码和当前的项目代码配置位于完正一致的情形。



打开代码中的任意有十个 多文件让我发现代码中的 package 声明的包名是 mgo,有些 和当前的目录名称上能 不一样,不过当前目录下所有的文件就有这同有十个 多包名 mgo。共同亲戚亲戚朋友儿还注意到即使是包内代码引用,还是使用了全路径来导入而就有相对导入,比如下图的 bson,难能可贵同属有十个 多项目,很久它们好像根本就互不相识,要使用对方的的路径全称来打招呼。



当其它项目导入有些 包时,import 语句底下的路径是 mongo 包的目录路径,而使用的包名却是有些 目录下面代码中 package 语句声明的包名 mgo。

go get vs go build vs go install

Go 提供了有十个 多比较的常用的指令用来进行全局的包管理。

讲到这里还有十个 多一阵一阵要的现象这样防止,github 上有有些开源项目,有些 项目就有多个版本号,我如可引入具体某有十个 多版本呢?将会使用 go get 指令,它一直 引入 master 分支的最新代码,它往往就有稳定的可靠代码。这就时需 Go 语言的依赖管理工具的支持了,它就好比 java 语言的 maven 工具,python 语言的 pip 工具。

原文发布时间为:2018-12-27

本文作者: 老钱

本文来自云栖社区合作协议伙伴“ 码洞”,了解相关信息上能 关注“

codehole”微信公众号



注意编译过程中第三方包的 main 包是不将会被编译的,安装的对象也就不将会包括第三方依赖包的可执行文件。

友好的包路径

Go 语言允许包路径含有网站域名,有十个 多它就上能 使用 go get 指令直接去相应的网站上拉去包代码。最常用的要数 github.com、gopkg.in、golang.org 有些 个多网址。



Go 语言不位于官方维护的集中包仓库,它将包的挑选分散到开源社区网站。使用量最大的要数 github.com,亲戚亲戚朋友儿平时使用的大偏离 第三方包就有来源于此。也上能 使用当事人公司提供的代码仓库,路径名用上公司代码仓库的域名即可。默认会使用 https 协议下载代码仓库 ,上能 使用 -insecure 参数切换到 http 协议。

当亲戚亲戚朋友儿使用 Go 语言自带的图像防止包时也会遇到匿名导入,在对图像进行编码解码的以前时需根据不同的图像编码挑选不同的逻辑。

当亲戚亲戚朋友儿使用 go run 指令来测试运行正在开发的系统守护进程时,将会发现启动了很久,这以前上能 考虑先执行 go build -i 指令,将编译成功的依赖包都安里装 GOPATH 的 pkg 目录下,有十个 多再次运行 go run 指令就会快有些。

dep ensure -add github.com/a/b

增加并下载有十个 多新的项目依赖包,上能 指定依赖版本号。如 dep ensure -add github.com/a/b@master 将会 github.com/a/b@1.0.0

有十个 多包的包名一样如可会会办?

将会你的代码时需使用有十个 多包,有些 个多包的路径最后有十个 多单词是一样的,那该如可分清使用的是那个包呢?为了防止有些 现象,Go 语言支持导入语句名称替换功能