go
提供了2种包管理方式,一种是go path
还有一种便是go mod
linux 使用
export
可以设置环境变量,例如:export GO111MODULE="on"
为什么需要包管理
在使用go
过程中,不仅需要使用系统提供的包,例如: fmt
、net
、log
等,我们还需要第三方包,例如: redis-go驱动github.com/go-redis/redis/v8
、mysql驱动github.com/go-sql-driver/mysql
,如何快速有效的导入并且使用这些第三方包,这就是为什么需要包管理。
go root
为什么需要go root
我们在安装完go后,需要设置go root
路径,当我们使用go
提供的系统库的时候,我们可以直接import
即可,无需安装,我们可以通过go env
来查看go root
设置,例如:
导入系统库案例
当我们程序使用导入系统库,例如: fmt
的时候,其实会先到go root
中进行寻找,例如,如下程序
我们import fmt
其实该库的绝对路径为/usr/local/go/src/fmt/print.go
由于我们设置了go root
,它会替我们寻找而已
go
为了导入第三方库,给我们提供了2个工具,分别为 go path
和go mod
。
我们从如下例子来讲go path
和go mod
go path
和go mod
设置- 引入本地依赖库
- 引入网络库
go path
go path 设置
我们也可以通过go env
来获得,例如
我们可以第三方插件放置到go path
目录下,然后引用即可
引入本地依赖
例如,我们新建一个新文件
路径: /root/go/src/github.com/pdudo/hello.go
内容
我们再主函数中引用该包函数Start
运行一下
若未找到包,则会报如下错误
报错意思为: 程序引用了该包,但是在go root
和go path
均未找到。
下载网络依赖
若我们引用了网络库,例如: redis-go
我们代码如下
在执行的时候,会报错
提示找不到github.com/go-redis/redis/v8
,我们只需要通过go get
即可进行下载
我们通过查看gopath
来看redis
库
这个代表下载好了,甚至于你可以通过这个命令来下载该库cd .; git clone -- https://github.com/go-redis/redis /root/go/src/github.com/go-redis/redis
最终目的只有一个,那就是将库放在go path
下即可。
缺点
- 使用
go get
,如遇网络问题,拉取过程较为复杂 - 自己编写的包,和网络上的第三方包,都放置在
go path
中,容易造成混乱,不方便管理 - 如果程序中导入了多个第三方包,第三方包又嵌套了第三方包,在
go get
的时候,往往会很困难。 - 使用
go get
,版本无法缺点,为应对该问题,往往需要设置多个目录
go mod
go
在v1.11
推出了go modules
包管理工具,以应对go path
出现的问题。
go mod设置
GO111MODULE
在go env
中有个环境变量: GO111MODULE
,该值来控制go mod
,其参数值为
- off
go
不启用go modules
功能,采取的是go path
方法来寻包。
- on
go
启用go modules
,若设置为on
,则不会寻找go path
路径了
- auto
该值较为特殊,是因为要根据当前目录环境来决定是否使用go modules
若出现如下情况,则会使用go mod
- 项目目录不在`go path`下 - 当前或者上一级目录存在`go.mod`文件
GOPROXY
在一些网络较为特殊的环境下,我们若没办法直接访问库地址,我们可以通过代理去镜像拉取
该值有2个参数: goProxyUrl,[off,direct]
若为off
: 表示不会回源,即: 当代理拉取不到数据的时候,不会去源站镜像拉取。
若为direct
: 表示会回源,当代理拉取不到的时候,会去源站尝试拉取
GOPRIVATE
和上面go env
变量 GOPROXY
呈现反效果,这里设置的是,不走proxy
的私有仓库或者项目。
设置类似于: GOPRIVATE=git.mycompany.com,github.com/my/private
我们测试设置如下
下载网络依赖库
我们可以使用go mod init mod_name
来创建一个go mod
其中mod_name
可以不写,然后使用go mod tidy
进行拉取资源
我们运行下程序
现在报的是连接不上redis
, 而非找不到库了。
引入本地依赖库
使用go mod
拉取网络库非常爽,但是引入个人库就比较麻烦了
例如,我们自己编写了一个flags
代码
我们想引用它,
我们先创建go mod
注意哟,这里如果要调用flags
库的函数,flags
也需要创建go mod
才行
go mod init
我们则需要修改一下go.mod
文件
修改如下
我们编写主函数
我们执行下代码
我们发现,代码执行成功了。
go.mod
含义
总结
不管是go path
也好,还是go module
也罢,找到自己合适的才是最好的,额, 不过,好像后续go
版本计划废除go path
,也不知道是不是真的,不过go mod
相比对go path
而言的话,上手较慢,需要有一个学习过程,才能正确引入本地依赖库。