资讯专栏INFORMATION COLUMN

GO111MODEDULE变量以及Go Module的使用建议

社区管理员 / 1244人阅读

我们可能在很多地方如 README 文件、Makefile 文件以及 Dockerfile 文件中看到GO111MODULE=on, 对于刚接触的Golang的开发者可能对此有很多疑惑。

这片文章,我将详细介绍GO111MODULE变量的意义,以及什么时候需要使用到该变量, 同时也总结了一些在使用 Go Modules 时需要注意的细节,帮助你在下次遇到这个变量时不再疑惑。

GO111MODULE=on go get -u golang.org/x/tools/gopls@latest

从 GOPATH 到 GO111MODULE

首先,对于 GOPATH,无论是资深开发者和新开发者都不会陌生。GO 在 2009 年发布时,并没有提供包管理器(Package manager), go get会根据导入路径拉取所有的源代码,存储在$GOPATH/src目录中。这种方式使用master分支作为包的稳定版本。 可想而知,这种方式缺乏灵活性同时很容易造成版本管理混乱的状态。

Go Modules(旧版本被成为vgo-versiond Go)在 Go 1.11 被正式引入,与 GOPATH 方式存储a signle git checkout of every package的方式不同, Go Module 通过go.mod文件管理包的版本信息,并且能够指定版本号。

两种包管理方式GOPATHGo Module同时存在,成为 Go 语言使用最大的坑,后续官方试图通过一个变量:GO111MODULE去解决这个问题, 不过随之而来的是更大的灾难。

GO111MODULE 环境变量

环境变量GO111MODUEL的作用是控制 Go 包导入的方式,可以设置为on,off,auto三个值,由于该变量的语意会根据 Go 的版本变化, 这在很多地方造成严重的歧义。

Go1.11 和 Go.12 版本 GO111MODULE

  • GO111MODULE=on无论项目是否在 GOPATH 目录,都会强制使用 Go Modules。

  • GO111MODULE=off无论项目是否在 GOPATH 目录,都会强制使用 GOPATH。

  • GO111MODULE=auto是默认模式,当项目不在 GOPATH 中会启用 Go Modules;当项目在 GOPATH 目录会强制使用 GOPATH。

当你的项目在 GOPATH 目录中,但是你又想使用 Go modules 下载一个指定版本的包或打包时,只能通过 GO111MODULE:

GO111MODULE=on go get github.com/golang/mock/tree/master/mockgen@v1.3.1

Go1.13 版本 GO111MODULE

在 Go 1.13 版本,GO111MODULE默认auto的用法发生了该改变:

  • 如果项目包含go.mod 或者项目不再 GOPATH 目录中(无论是否包含go.mdo文件)都会使用 Go module。所以使用 Go 1.13, 你可以将所有项目保存到 GOPATH 中。

  • 只有在项目保存在GOPATH中同时又不包含文件go.mod文件时,才会使用GOPATH

为什么很多地方使用 GO111MODULE

Go Module可以通过git tag控制项目依赖包的版本,而GOPATH默认拉取master分支的最新提交。 环境变量GO111MODULE控制了是否启用 Go module。我们则可以GO111MODULE=on go get xxxx/@1.33的方式拉取指定版本的包。

GO111MODULE=on go get -u golang.org/x/tools/gopls@latest
GO111MODULE=on go get -u golang.org/x/tools/gopls@master
GO111MODULE=on go get -u golang.org/x/tools/gopls@v0.1
GO111MODULE=on go get golang.org/x/tools/gopls@v0.1.8

latest标签使用最新版本 git tag。-u选项强制更新,在指定版本是这个选项没有意义。

使用 Go Modules 的建议

其实在新版本Golang中,如果不接触旧的项目,可以不用关注这个变量意义。这里总结了使用 Go Modules 的一些建议

记住 go get 将会更新 go.mod 文件

go get主要用于下载依赖包和安装二进制文件,但是当项目中存在go.mod文件,使用go get会自动修改go.mod文件。 这听起来很奇怪,但这也是 Go modules 的一大亮点:自动维护依赖包版本。

在一些CICD流程中,我们需要注意这点。比如当使用Jenkins时,其会在 slave 节点workspace目录中上拉取代码,如果需要执行一些脚本命令时, 如测试,编译等,如果项目依赖有变化,则go.mod文件会产生修改,这就导致下次执行构建时,产生错误。

image.png

这里提供有两种方式解决,一种方法是添加一个clean stage,丢弃暂存区的修改记录;还有一种通过容器方式进行构建。 关于Golang项目CICD流程优化有机会会在后续多带带写一篇博客系统介绍,这里只提一下。

Go Module 的依赖源来自哪里

当使用 Go Modules,go build会使用存储在$GOPATH/pkg/mod下的包,在使用 vim、VScode 等编辑器开发 Golang 项目, 可能默认会使用 GOPATH 中的包而不是使用 pkg/mod。

第二个问题是当我们在测试时需要替换一个包版本时,通常有以下几种做法:

Solution 1: 使用go mod vendor + go build -mod=vendor,这将会强制 go 使用 vendor/目录下的包,而不是$GOPATH/pkg/mod 中包

Solution 2: 在go.mod文件中使用replace../beers是相关依赖的 copy。

use replace github.com/maelvls/beers => ../beers

私有 Go modules 和 Dockfile

在公司中,通常会使用很多私有仓,我们可以使用GOPRIVATE去设置让Go跳过包代理,直接从私有代码仓拉取包。 但是但我们使用 docker 构建镜像时,如何拉取私有仓呢,有以下方案

  1. vendoring: 使用go mod vendor,这样就不要传递私有仓凭证给 docker build context。因为所有依赖都保存在 vendor 目录 中,构建时需要使用选项-mod=vendor

  • 优点:加速 docker 镜像构建,(go mod download 和 docker cache 配合使用也可以优化构建速度)

  • ENV GOPROXY https://goproxy.io
    WORKDIR /workspace
    ## All these steps will be cached
    COPY go.mod go.sum ./
    ## Get denpendencies will also be cached if wo don't change go.mod and go.sum
    RUN go mod download
  • 缺点:代码管理复杂,需要跟踪依赖包的更新

  1. no vendoring: 如果vendor/目录很大(kubernetes vendor 目录大约是 30MB),这种情况使用 vendoring 的方式会 很糟糕,这时候可以通过定义变量GITHUB_TOKEN传递给 dockerfile 文件。

  2. ENV GOPROXY https://goproxy.io
    WORKDIR /workspace
    ## All these steps will be cached
    COPY go.mod go.sum ./
    ## Get denpendencies will also be cached if wo don't change go.mod and go.sum
    RUN go mod download


文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/127930.html

相关文章

  • golang 学习环境准备

    摘要:下载在命令行执行可以查看到结果说明安装成功设置环境变变量还是按照上述环境变量的配置方式进入系统变量中输入变量名和变量值,变量名变量值或者或者推荐选择无模块支持,会从和文件夹寻找包。模块支持,会忽略和文件夹,只根据下载依赖。 Downloads - The Go Programming La...

    Airmusic 评论0 收藏0
  • 程序员笔记——如何编写优雅Dockerfile

    摘要:导读要从容器化开始,而容器又需要从开始,本文将介绍如何写出一个优雅的文件。只要记住以上三点就能写出不错的。执行完成项目的构建。 导读 Kubernetes要从容器化开始,而容器又需要从Dockerfile开始,本文将介绍如何写出一个优雅的Dockerfile文件。 文章主要内容包括: Docker容器 Dockerfile 使用多阶构建 感谢公司提供大量机器资源及时间让我们可以实践...

    曹金海 评论0 收藏0
  • 区块链教程Fabric1.0源代码分析flogging(Fabric日志系统)兄弟连区块链

    摘要:区块链教程源代码分析日志系统,年下半年,区块链行业正逐渐褪去发展之初的浮躁回归理性,表面上看相关人才需求与身价似乎正在回落。源代码笔记之日志系统概述,即,对第三方日志包做了封装,供全局使用。设置各模块的日志级别,并更新。   区块链教程Fabric1.0源代码分析flogging(Fabric日志系统),2018年下半年,区块链行业正逐渐褪去发展之初的浮躁、回归理性,表面上看相关人才需...

    DandJ 评论0 收藏0

发表评论

0条评论

社区管理员

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<