Please enable Javascript to view the contents

一起来学 Go --(3)Go Modules

 ·  ☕ 3 分钟

1. Go 的包管理机制

1.1 GOPATH

GOPATH 通过 go get 命令,拉取代码放到 GOPATH 目录中。

GOPATH 的问题是:

  • 不能进行包版本的管理
  • 使用全局仓库,不能有效进行隔离

1.2 Vendor

1.5 版本开始,Go 中加入了 Vendor 机制。Vendor 解决了 GOPATH 的部分问题。

Vendor 机制通过在项目目录下增加 vendor 文件夹,管理依赖包。

Vendor 的问题是:

  • 无法解决嵌套依赖
  • vendor 只在 GOPATH 路径下有效

1.3 Go modules

Go modules 允许项目代码放在任意目录,依赖包统一保存在 $GOPATH/pkg/mod 目录下,避免了 vendor 方案的重复代码。

2. Go modules 特征

Go 通过 GO111MODULE 开关变量,控制 Go modules 特性是否启用,可选值有三个 : auto/on/off 。1.11 版本开始引入,默认值为 auto,1.13 版本默认开启。

auto 的含义是,当前目录下有 go.mod 则开启。auto 模式下:

  • 在 GOPATH 目录下编译时,默认使用 vendor、GOPATH 进行包管理
  • 在 GOPATH 目录外编译时,默认使用 go.mod 设置进行包管理。

在 Go modules 使用过程中,会自动生成两个文件 go.sum 和 go.mod。通常,会将这两个文件也提交到代码仓库。

  1. go.mod

go.mod 记录了依赖包的版本信息和操作命令。go.mod 提供了 module、require、replace、exclude 四个命令。

1
2
3
4
cat go.mod
module github.com/project/hello
go 1.12
require rsc.io/quote v3.1.0+incompatible
  1. go.sum

go.sum 提供了版本校验值。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
cat go.sum
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c h1:qgOY6WgZOaTkIIMiVjBQcw
93ERBE4m30iBm00nkL0i8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3
fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
rsc.io/quote v3.1.0+incompatible h1:5v8TkzZ3hgTuFV/P47Ib17+Lc9DHpLRa+HPYYhT/X9
o=
rsc.io/quote v3.1.0+incompatible/go.mod h1:LzX7hefJvL54yjefDEDHNONDjII0t9xZLPX
sUe+TKr0=
rsc.io/sampler v1.3.0 h1:7uVkIFmeBqHfdjD+gZwtXXI+RODJ2Wc4O7MPEh/QiW4=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

3. 配置代理

在安装 Go 依赖包时,会对外网请求数据。有些包托管在 github.com ,还有些包托管在 golang.org 、k8s.gcr.io 等仓库。由于 google 相关的网址被屏蔽,经常会遇到网络无法访问的问题。

在 1.11 版本中,新增了一个环境变量 GOPROXY ,可以用来配置代码仓库镜像代理。

以配置 jfrog 提供的 GoCenter 为例,在运行环境执行:

1
export GOPROXY=https://gocenter.io

即可,使用 jfrog 提供的代理。除此,GoCenter 还提供了包搜索的功能。

当然,aliyun 也提供了 GOPROXY :

1
export GOPROXY=https://mirrors.aliyun.com/goproxy/

4. Go modules 基本命令

Go modules 帮组文档,已经描述得十分详细。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
go help mod
Go mod provides access to operations on modules.

Note that support for modules is built into all the go commands,
not just 'go mod'. For example, day-to-day adding, removing, upgrading,
and downgrading of dependencies should be done using 'go get'.
See 'go help modules' for an overview of module functionality.

Usage:

	go mod <command> [arguments]

The commands are:

	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(将当前目录初始化为新模块)
	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(解释为什么需要依赖)

Use "go help mod <command>" for more information about a command.
  1. 新建一个目录 hello,目录中新增文件 hello.go
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
cat hello.go
package main

import (
    "fmt"
    "rsc.io/quote"
)

func main() {
    fmt.Println(quote.Hello())
}
  1. 初始化包为仓库地址
1
go mod init github.com/project/hello
  1. 编译,生成可执行文件
1
go build
  1. 将依赖包归档到项目 vendor 目录
1
2
3
4
5
6
7
8
go mod vendor -v
# golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c
golang.org/x/text/language
golang.org/x/text/internal/tag
# rsc.io/quote v3.1.0+incompatible
rsc.io/quote
# rsc.io/sampler v1.3.0
rsc.io/sampler
  1. 验证依赖
1
2
go mod verify
all modules verified
  1. 查看最终目录结构
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
tree -L 2
.
├── go.mod
├── go.sum
├── hello
├── hello.go
└── vendor
    ├── golang.org
    ├── modules.txt
    └── rsc.io

5. 参考


微信公众号
作者
微信公众号