Go 依赖管理是通过 Git 仓库模式实现,并随着版本的更迭逐渐完善。
早期是 GOPATH 模式:GOPATH 目录是所有工程的公共依赖包目录,所有需要编译的 go 工程的依赖包都放在 GOPATH 目录下。
后续引入多版本支持的 Vendor 特性:go 1.6 之后开启了 vendor 目录,以支持各个工程对于不同版本的依赖包使用的需求(每个工程拷贝一份代码)。
Go Module 管理:Go1.11 实现了依赖包的升级更新,在 Go1.13 版本后默认打开。
# GOPATH
GOPATH 为 Go 开发环境时所设置的一个环境变量。
历史版本的 go 语言开发时,需要将代码放在 GOPATH 目录的 src 文件夹下。go get 命令获取依赖,也会自动下载到 GOPATH 的 src 下。以下命令会将代码下载到 $GOPATH/src/github.com/foo/bar
。
go get github.com/foo/bar
GOPATH 具体结构如下,必须包含三个文件夹:
GOPATH
|-- bin 二进制文件
|-- pkg 预编译文件(加快后续编译速度)
|-- src 源代码
|-- github.com
2
3
4
5
# GO Modules
从 Go 1.11 开始初步支持,解决了依赖版本的信息管理,并且保证安全性 。
由 go.mod 和 go.sum 组成,包括依赖模块路径定义,通过 checksum 保证包的安全性,并且可以在 GOPATH 外创建和编译项目。
使用 go mod init
命令初始化项目,生成 go.mod 文件:
go mod init example.com.hello
cat go.mod
2
module example.com/hello
go 1.16
2
3
使用 go get github.com/sirupsen/logrus
可下载或更新依赖包:
module example.com/hello
go 1.16
require github.com/sirupsen/logrus v1.8.1
2
3
4
5
各关键字含义:
- module: 定义当前项目的模块路径。
- go: 标识当前模块的 Go 语言版本。
- require: 依赖包及其版本。
- exclude: 在使用中排除特定的模块版本。
- replace:替换 require 中声明的依赖,使用另外的依赖及其版本号。
Checksum
为解决 Go Modules 的包被篡改的安全隐患,引入 go.sum 文件以记录每个依赖包的哈希值,在构建时如果本地的依赖包 hash 值与 go.sum 文件中记录的不一致,则会拒绝构建。
- go.sum 文件中每行记录由 module 名、版本和哈希组成,以空格分隔。
- 引入新依赖时,通常使用
go get
命令获取,将包下载到本地缓存目录$GOPATH/pkg/mod/cache/download
,该包后缀为 .zip,并把哈希运算同步到 go.sum 文件中。 - 在构建应用时,从本地缓存中查找所有 go.mod 中记录的依赖包,并计算本地包的哈希值 ,与 go.sum 中的记录对比,如果校验失败,go 命令将拒绝构建。
# Proxy
Go 1.13 的 GOPROXY 默认为 https://proxy.golang.org,在国内需要配置代理才能使用。GOPROXY (opens new window) 也可以解决公司内部的使用问题:
- 访问内网的 git server。
- 防止公网仓库变更导致线上编译失败或者紧急回退失败。
- 满足公司审计和安全需要。
- 防止内部开发人员配置不当造成 import path 泄露。
- cache 热点依赖,降低公司公网出口带宽。
export GOPROXY=https://goproxy.io,direct
# 不走 proxy 的私有仓库或组,以逗号分隔。
export GOPRIVATE=git.mycompany.com,github.com/my/private
2
3
# Private
用于控制 go 命令把某些仓库视作私有仓库,可以跳过 proxy server 和 checksum 检查,GOPRIVATE 的值同时作为 GONOPROXY 和 GONOSUMDB 默认值:
# 以逗号分隔。
export GOPRIVATE=*.corp.example.com,github.com/org_name
2
推荐同时配置 GOPROXY 和 GOPRIVATE 使用,GOPRIVATE 也可以识别 Git SSH KEY 进行权限效验。
# GOPROXY 编译部署
goproxy.io 是 Go Modules 开源代理,也可作为公司内部代理。
# 下载编译:
git clone https://github.com/goproxyio/goproxy.git
cd goproxy
go build
# 运行代理:
# ./goproxy -listen=0.0.0.0:8081 -cacheDir=/tmp/cache -proxy https://goproxy.io -exclude "github.com/private"
#
# -cacheDir 指定 Go 模块的缓存目录
# -exclude proxy 模式下指定不经过上游服务器的 path
# -listen 服务监听端口,默认 8081
# -proxy 指定上游 proxy server,推荐 goproxy.io
2
3
4
5
6
7
8
9
10
11
12
访问内网 Git 仓库:
- 用户本地配置
GONOSUMDB=github.com/private
- goproxy server 配置 exclude 进行排除所代理仓库
- goproxy server 配置 SSH Key,并且在仓库添加只读权限
- goproxy server 配置 .gitconfig 把 ssh 替换成 http 方式访问
[url "git@github.com:"]
insteadOf = https://github.com/
[url "git@github.com:"]
insteadOf = https://gitlab.com/
2
3
4