go modules 基础

2020-07-14  本文已影响0人  _张晓龙_

引言

go 语言支持 go modules 特性已经快两年了,但很多项目由于种种原因还没有实施迁移。这几天想写一篇文章,全面的阐述一下 go modules 特性,使得读者快速掌握其要点,从而低成本的将项目的包管理迁移到 go modules。

考虑到实战部分的内容较多,将计划的一篇文章拆分为多篇来呈现,一层层的慢慢揭开 go modules 的神秘面纱。本文为开篇,主要介绍 go modules 的基础知识。

go modules 背景

在 go1.5 发布后的若干年,gophers 把注意力都集中在如何利用 vendor 机制来解决包依赖问题,从手工添加依赖到 vendor、手工更新依赖,到一众包依赖管理工具的诞生,比如: govendorglide 以及号称准官方工具的 dep,都在努力地尝试着按照当时的主流思路来解决诸如“钻石型依赖”等难题。

正当 gophers 认为 dep 将“顺理成章”地转正为 go toolchain 一部分的时候,vgo 横空出世,并通过对 “Semantic Import Versioning” 和 ”Minimal Version Selected” 的设定,在原 go tools上简单快速地实现了 go 原生的包依赖管理方案 这个 vgo 就是 go modules 的前身。

go modules 定义

通常,我们会在一个 go 代码库中创建一组包,而代码库的路径会作为包的导入路径,比如 github.com/agiledragon/gomonkey。在 go1.11 版本中,给在同一代码库下面的这样一组包定义了一个新的概念叫 modulemodule 根目录一般叫 module root 目录。

一个代码库只有一个 module 吗?一般情况是这样,但也可以有多个 module

go mod可以看作是 go modules 的简称。

go mod 配置

go1.11 在引入 go modules 特性时,增加了一个特性开关(环境变量)GO111MODULE,对应的值有三个:auto,on,off。

下面详细解释一下这三个值的含义:

GOPATH mode & GOPATH 环境变量

使用 module-aware mode 后,用户可以不用再配置 GOPATH 环境变量了,但细心的读者可能已经发现 go mod 命令的缓存目录为 $GOPATH/pkg/mod

那到底还要不要配置GOPATH 环境变量了?

从 go1.8 版本开始,GOPATH 有了默认值,即 $HOME/go。如果用户配置了 GOPATH 环境变量,则覆盖默认值。所以,在 module-aware mode 下,不管用户是否配置了 GOPATH 环境配置,$GOPATH 都有确定的值,无非是否为默认值的问题,所以 go mod 命令的缓存目录 $GOPATH/pkg/mod 是有效的。

综上,使用 go modules 机制管理依赖包后,我们弃用的是 GOPATH mode,而不是 GOPATH 环境变量,当然你也可以不设置 GOPATH 环境变量,go 编译器直接使用 GOPATH 默认值也 OK。

go mod 命令

go 编译器提供了 go mod 命令来管理依赖包。

go mod 主要包括下命令:

命令 说明
download download modules to local cache(下载依赖包)
edit edit go.mod from tools or scripts(编辑go.mod)
graph print module requirement graph (打印模块依赖图)
init initialize new module in current directory(在当前目录初始化mod)
tidy add missing and remove unused modules(拉取缺少的模块,移除不用的模块)
vendor make vendored copy of dependencies(将依赖复制到vendor下)
verify verify dependencies have expected content (验证依赖是否正确)
why explain why packages or modules are needed(解释为什么需要依赖)

go mod 文件

go mod 文件主要包括 go.mod 和 go.sum,这两个文件在 module root 目录下,都要提交到代码库。

使用 go mod 管理依赖后,在 module root 目录下:

go.mod 文件提供了 module,require,replace 和 exclude 等命令:

goconvey 测试框架的 go.mod 文件:

module github.com/smartystreets/goconvey

require (
    github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 // indirect
    github.com/jtolds/gls v4.20.0+incompatible
    github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d
    golang.org/x/tools v0.0.0-20190328211700-ab21143f2384
)

goconvey 测试框架的 go.sum 文件:

github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384 h1:TFlARGu6Czu1z7q93HTxcP1P+/ZFC/IKythI5RzrnRg=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=

go proxy

顾名思义,go proxy 是 go 语言的代理,一般是配合 go modules 使用,可以使用户方便且快速的获取第三方包,尤其是 go 官方的一些包。

作者本机配置的 go proxy 为:

bogon:~ zhangxiaolong$ echo $GOPROXY
https://goproxy.cn,direct

go 团队包管理从传统 GOPATH mode 迁移到 module-aware mode 后,代码库中没有了 vendor 目录,而增加了 go.mod 文件和 go.sum 文件。在 CI 流水线上编译版本时,需要实时获取依赖,但从外网下载所有依赖的第三方包有一些问题:

此时,在公司内网搭建一个私有的 go proxy 就使得这些问题迎刃而解。

小结

本文主要介绍了 go modules 的基础知识,包括背景、定义、配置、模式、命令、文件和代理等内容,希望对读者感性认识 go modules 特性有一定的帮助。

下一篇文章将开启实战部分,作者将使用 go1.14 版本,通过一些小案例来初步解析 go modules 机制,名字叫啥好呢?
“什么天长地久,只是随便说说,你爱我那一点,你也说不出口......”。突然,听到了张震岳的成名曲《爱的初体验》,要不下一篇文章就叫 《go modules 初体验》

上一篇下一篇

猜你喜欢

热点阅读