学习golang(9) 初探:go path与go mod

675 阅读4分钟

go提供了2种包管理方式,一种是go path还有一种便是go mod

linux 使用 export可以设置环境变量,例如:export GO111MODULE="on"

为什么需要包管理

在使用go过程中,不仅需要使用系统提供的包,例如: fmtnetlog等,我们还需要第三方包,例如: 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 pathgo mod

我们从如下例子来讲go pathgo mod

  1. go pathgo mod设置
  2. 引入本地依赖库
  3. 引入网络库

go path

go path 设置

我们也可以通过go env来获得,例如

我们可以第三方插件放置到go path目录下,然后引用即可

引入本地依赖

例如,我们新建一个新文件

路径: /root/go/src/github.com/pdudo/hello.go

内容

我们再主函数中引用该包函数Start

运行一下

若未找到包,则会报如下错误

报错意思为: 程序引用了该包,但是在go rootgo 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

gov1.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而言的话,上手较慢,需要有一个学习过程,才能正确引入本地依赖库。