go 包管理前世今生

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/wenzhou1219/article/details/88760066

按照历史来说,目前go1.12为止,官方有三种包管理方式,分别是:

  • 原始的GOPATH
  • 1.9开始支持的go dep
  • 1.11开始支持的go modules

三种方式并不是后者淘汰前者,就目前来看各有各的使用场景,新的兼容旧的方式,如果新学习的话建议直接使用go modules。

GOPATH

GOPATH是最开始自带的管理方式,所有的项目共用一个工作区,工作区通过GOPATH设置,推荐的目录结构如下:

gopath目录结构

这里推荐的做法是设置一个全局的GOPATH,所有的项目包括go get拉取的包都在这个src下,这可能是和go最开始就是为google开发的语言,他们内部就是这种超大代码目录共享的方式开发的。然而对于实际项目使用中,这样存在多个不变,包括:

  • 多个项目都混在同一个src中,不便于管理
  • 不同项目依赖的公共库只能是版本一致的
  • 项目的依赖都必须自己手动 go get去拉取,十分不方便

针对这种情况,go官方推出了dep工具,讲dep之前注意看下如下两个常见问题:

多个工作区问题

GOPATH可设置多个工作区,Windows以;分割,Linux以:分割。引入库时,按照GOPATH设置的顺序查找工作区中库,优先查找GOROOT中的库,不同工作区中相同的库只会导入入最先查找到的库。有些开发工具,比如GOLAND允许定义项目级的GOPATH,其实就是编译时动态设置下环境变量。

相同后缀路径导入问题

默认导入库使用时以最后一级为包名,但是如果两个最后一级相同的包怎么导入?比如

  • src/dir1/flag
  • src/flag

导入时使用包名都是flag,如果同时导入,编译会报冲突,这种情况分别设置别名即可,如下导入语句:

  • import a “dir1/flag”
  • import b “flag”

dep包管理

go在1.5引入了vender机制,也就是如果当前项目下有vender目录,那么优先从vender目录查找依赖,这样之后出现了很多依赖管理工具如godep、glide等,他们解决了之前的两个问题

  • 不同项目可以把自己依赖的工程放在vender中,这是自己独有的依赖,甚至可以直接把vender目录提交到代码库管理
  • 自动解析依赖关系,只需要编写类似maven的依赖文件即可完成依赖库自动下载

为了解决各家推出的依赖管理工具各有不同的问题,go官方推出了go dep工具统一这些管理。
dep操作很简单,dep init初始化后会在当前目录下建立Gopkg.toml、Gopkg.lock文件来管理依赖,vender目录来存放依赖,具体使用可参考这篇文章

然而dep还是存在它的问题:

go modules包管理

就目前来看go modules应该是一个终极解决方案,在go 1.12中已经集成,它允许我们在任意的地方新建项目,对应的依赖存在GOPATH/pkg/mod中,GOPATH不再作为项目必须所在的工作区。

go modules操作非常简单,go mod init后会新建一个go.mod文件管理依赖,具体build后会下载对应依赖,并且用go.sum来保证下载的依赖是没有被篡改的。具体使用你可以参考如下文章:

另外针对之前说的访问失败问题,现在可以直接指定GOPROXY环境变量来设置包拉取代理,常用https://proxy.io;如果用户习惯了vender模式或者希望从之前的vender模式无缝过渡,那么go build -mod=vender参数会管用。

当然,go modules并非完美, 它存在多版本管理缺陷和嵌套引用冲突问题。相信这些在新版本中都会陆续被解决。

原创,转载请注明来自

猜你喜欢

转载自blog.csdn.net/wenzhou1219/article/details/88760066