Skip to content

包引用与依赖管理

Go 语言依赖管理的演进

  • 回顾 GOPATH
    • 通过环境变量设置系统级的 Go 语言类库目录
    • GOPATH 的问题?
      • 不同项目可能依赖不同版本
      • 代码被 clone 以后需要设置 GOPATH 才能编译
  • vendor
    • 自 1.6 版本,支持 vendor 目录,在每个 Go 语言项目中,创建一个名叫 vendor 的目录,并将依赖拷贝至该目录。
    • Go 语言项目会自动将 vendor 目录作为自身的项目依赖路径
    • 好处?
      • 每个项目的 vendor目录是独立的,可以灵活的选择版本
      • Vendor 目录与源代码一起 check in 到 github,其他人 checkout 以后可直接编译
      • 无需在编译期间下载依赖包,所有依赖都已经与源代码保存在一起

vendor管理工具

通过声明式配置,实现 vendor 管理的自动化

  • 在早期,Go 语言无自带依赖管理工具,社区方案鱼龙混杂比较出名的包括
    • Godeps, Glide
  • Go 语言随后发布了自带的依赖管理工具 Gopkg
  • 很快用新的工具 gomod 替换掉了 gopkg
    • 切换 mod 开启模式:export GO111MODULE=on/off/auto
    • Go mod 相比之前的工具更灵活易用,以基本统一了 Go 语言依赖管理

思考:用依赖管理工具的目的?

  • 版本管理
  • 防篡改

Go mod 使用

  • 创建项目
  • 初始化 Go 模块
    • go mod init
  • 下载依赖包
    • go mod download(下载的依赖包在$GOPATH/pkg,如果没有设置 GOPATH,则下载在项目根目录/pkg)
    • 在源代码中使用某个依赖包,如 github.com/emicklei/go-restful
  • 添加缺少的依赖并为依赖包瘦身
    • go mod tidy
  • 把 Go 依赖模块添加到 vendor 目录
    • go mod vendor

配置细节会被保存在项目根目录的 go.mod 中,可在 require 或者 replacement 中指定版本

go.mod sample

module k8s.io/apiserver
go 1.13
require (
    github.com/evanphx/json-patch v4.9.0+incompatible
    github.com/go-openapi/jsonreference v0.19.3 // indirect
    github.com/go-openapi/spec v0.19.3
    github.com/gogo/protobuf v1.3.2
    golang.org/x/crypto master
    github.com/google/gofuzz v1.1.0
    k8s.io/apimachinery v0.0.0-20210518100737-44f1264f7b6b
)

replace (
    golang.org/x/crypto => golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975
    golang.org/x/image => github.com/golang/image
    k8s.io/api => k8s.io/api v0.0.0-20210518101910-53468e23a787
    k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20210518100737-44f1264f7b6b
    k8s.io/client-go => k8s.io/client-go v0.0.0-20210518104342-fa3acefe68f3
    k8s.io/component-base => k8s.io/component-base v0.0.0-20210518111421-67c12a31a26a
)

GOPROXY 和 GOPRIVATE

  • GOPROXY
    • 为拉取 Go 依赖设置代理
      • export GOPROXY=https://goproxy.cn
  • 在设置 GOPROXY 以后,默认所有依赖拉取都需要经过 proxy 连接 git repo,拉取代码,并做 checksum 校验
  • 某些私有代码仓库是 goproxy.cn 无法连接的,因此需要设置 GOPRIVATE 来声明私有代码仓库
GOPRIVATE=*.corp.example.com
GOPROXY=proxy.example.com
GONOPROXY=myrepo.corp.example.com