本人从事Go语言开发多年,目前主要从事云计算相关开发。
写本公众号的目的主要是对自己的过往知识进行梳理,也希望可以帮助大家学习~
后续会推出Go语言源码学习系列和web开发系列等,欢迎大家关注。
前面我们提到:常量和变量都是数据的一种载体,数据通过不同的运算符参与运算时,对计算的流程进行一定程度的控制便是流程控制,并且对于较多的数据通过内置容器进行存储,然后通过对以上的所有概念进行整合,通过函数完成某一特定的功能。相同类型的函数在同一文件中进行呈现,那么当越来越多的文件需要管理时,便是本篇文章的主要话题——包管理。通过包的方式对代码进行最有效的管理。
包 是一个重要的概念,我们将详细介绍,那么该如何进行思考和学习呢?
思维逻辑图如下:
下面我们从以上三个方面对 包 这一概念进行相应的介绍
我们一般提到包的位置指的是项目包的位置,其实项目包是被包含于工作区或者工作目录
,而工作区或者工作目录就是我们经常碰到的GOPATH。比如说,我们创建了一个叫做myWeb的项目包,该包是一个关于博客web的小项目,这个项目包则被包含于GOPATH工作区目录。
所以我们下面首先对工作区GOPATH进行介绍,然后对与GOPATH紧密相关的GOROOT进行介绍
当我们在命令行执行go env时,会呈现出很多与go环境信息相关的内容,其中包括GOPATH和GOROOT,如下
图中GOPATH = D:\GoProgram,即是我们的工作区,也就是说D:\GoProgram即是当前工作区,那么我们先对工作区的结构进行介绍。
1)工作区的结构
工作区目标一般包含三个子目录,分别为:src目录,pkg目录以及bin目录。
a) src目录:src目录就是对我们写的go语言代码进行保存的地方,就像上文提到的myWeb项目,而且go语言进行编译时查找代码就在这个src目录查找;
b) pkg目录:pkg目录是对go get/go install命令执行后生成的“.a”文件进行保存,c语言中是指编译后生成的静态库文件,当然,go语言编译生成的lib文件也保存在这里;
c) bin目录:bin目录是对go get/go install命令执行后生成的二进制可执行文件进行保存,在windows系统中就是.exe结尾的文件;
注:以上三个目录,对于pkg目录和bin目录不需要我们主动创建,因为在执行相关命令时比如go install 会自动创建目录,但是src目录需要我们主动去创建。
2)工作区的设置
GOROOT即是Go语言的安装目录,这个目录我们平常接触的没有GOPATH多,这里我们对这个目标下的子目录进行简要介绍。安装目录下的子目录如下
g) src目录:Go标准库文件;
h) test目录:Go语言官方自带的一些测试文件;
包的声明相对比较简单,主要是通过Golang的关键字package 和包的名字结合的方式来声明,如下:
package main //表示声明了一个名为main的包
注:main包具有特殊性,有且仅有一个,Go语言会将main包编译为二进制可执行文件,
在这里我们小插一点内容:关于Golang中变量的可见性,即访问权限的介绍:
Golang语言对于变量以变量名的首字母的大小写来体现访问权限的大小。
1)首字母大写,代表包外可见;
2)首字母小写,代表仅包内可见;
但是对于包名我们通常应该用小写字母
依赖包管理是指对第三方依赖包的管理,比如从GitHub上下载的代码。那么为什么需要对依赖包进行管理呢?其实是因为我们在第三方库下载的代码不具有持续稳定性,比如一段时间后可能这个库代码更新升级了,而且还不向下兼容,更有甚者直接删除了等等。所以为了项目的稳定运行,须对依赖包进行管理
下面我们对golang依赖包管理的发展历程进行介绍,主要是三个阶段:GOPATH,vendor和现在的go mod
最早的GOPATH依赖包管理是将所有的本地代码和第三方包代码均放在GOPATH/src目录下,它的优点是统一管理,方便查询和引用。
但是在使用过程中也会有一个非常严重的坑,那就是由于所有不同的项目均放在GOPATH/src目录下,当多个不同项目引用的是同一个第三方包,但是该第三包的不同版本时,便会导致严重的包依赖问题。
大家可能会想,在前面工作区配置中,我们不是可以配置多个工作区吗,我们配置多个工作区,不就可以将本地代码和第三方包依据不同项目隔离开了吗,但是怪就怪在,go get获取代码时,当你配置了多个工作区时,它只会下载到第一个工作区目录
所以这也是Go语言之初被诟病的一个点
对于依赖包管理的问题,在GOPATH中我们也提到,最好的方式是对依赖包根据项目进行隔离。
所以在go的1.5版本中引入了一个新的属性:vendor,对应的环境变量是GO15VENDOREXPERIMENT,默认关闭(设置为1开启),在1.6版本中默认设置为1开启
vendor属性的作用便是:在进行编译时,优先从vendor目录下查找代码,如果没有才回去GOPATH下查找,有的话便不会再进行查找
但是同样vendor也有一个问题:vendor目录没有对版本信息进行保存,所以当版本升级,版本追溯都会有困难;而且如何方便的进行依赖包拷贝也是一个问题
为了解决这些问题,社区里出现了几个代表性的工具:godep,golide和govendor,这三个工具中govendor的使用相对更多一些
主要有如下几个主要命令:
init 初始化vendor目录
get 拉取依赖包到vendor目录
add 添加依赖包到vendor目录
update 更新依赖包到vendor目录
remove 从vendor目录中删除依赖包
go mod的出现结束了依赖包管理的混乱现象。go mod是go 1.11版本出现的,对应的环境变量是:GO111MODULE(on代表开启)。go mod的出现使依赖包的管理变的更为简单,而且可以独立GOPATH和vendor存在。
go mod依赖包管理方式有两个文件:go.mod和go.sum
如上图所示:
a. module 定义项目包名
b. Require 定义依赖包以及版本
c. Indirect 表示是间接引用
go.sum的形式为:
module 版本号/go.mod h1:哈希值
其中module是依赖的路径,version是依赖包的版本号,hash是以h1:开头的字符串
go mod主要的命令有:
init 将当前文件夹初始化为新的module,生成go.mod文件
tidy 对丢失的module就行导入,对多余的删除
vendor 将依赖复制到vendor目录下
以上是依赖包管理的发展历程,主要是为了理解来龙去脉增进理解。现在在使用中,我们优先使用go mod
到此关于Golang包的分享就结束了~
此篇为Go语言基础系列分享第六篇,欢迎大家关注本公众号《Go开发与计算机技术》,Go语言基础系列学习不迷路。