Go 包管理工具

Table of Contents

1. [deprecated] govender

govendor: https://github.com/kardianos/govendor,安装: go get -u github.com/kardianos/govendor

1.1. 创建项目

  • 项目初始化: govendor init
  • 查看文件状态: govendor list
  • 添加 package 到 vendor: govendor add +external

1.2. 常规使用

  • git pull 下来项目后,本地同步安装 package: govendor sync -v
  • 查看 package 被哪里引用: govendor list -v package
  • govendor 其实并不那么好用(不然 go 的 package 管理也不会这么混乱了),升级和删除 package 等,暴力解法是:删掉 vendor 目录,重新走一遍初始化

2. Go module

官方的几篇介绍文章:

  1. Using Go Modules
  2. Migrating to Go Modules
  3. Publishing Go Modules
  4. Go Modules: v2 and Beyond

Go 1.11 之后官方支持包管理工具 go mod

Usage:

    go mod <command> [arguments]

The commands are:

    download    download modules to local cache
    edit        edit go.mod from tools or scripts
    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
    verify      verify dependencies have expected content
    why         explain why packages or modules are needed

2.1. 常见场景

  • 初始化: go mod init 会生成 go.mod 文件;如果在 GOPATH 之外的项目, go mod init 需要指定仓库名称
  • 添加依赖:如果 Go 发现有新的 package 引入,在执行 go build 或者 go test 会自动 finding->downloading->extracting,然后将 package 名称和版本写入到 go.mod 文件中。 引入一个 package,package 可能还依赖其它的 package,go.mod 只记录根依赖,你可以通过 go list -m all 来查看所有的依赖; 除了 go.mod 之外,还生成了一个 go.sum 文件用来做 hash 校验; go.mod 和 go.sum 都应该放到版本管理工具中
  • 升级依赖, go get -u 包之后,go.mod 会自动升级到最新版本;
    • go list -m -u all 可以查看包的可升级版本
  • 移出不常用的依赖 go mod tidy
  • go mod download 下载依赖的 module 到本地缓存
  • go mod why 查找包的依赖,比如 go mod why golang.org/x/text/encoding
  • go clean -modcache 删除所有的 mod 目录下的文件,注意是所有的,并不是本项目的1

2.2. vendor 目录说明

从上面的几篇文章可以看到基本上没有再提 vendor 目录的事,虽然 go mod 命令确实有支持。 官方 wiki 里有说明: How do I use vendoring with modules? Is vendoring going away?

Go modules 的设计之初是想完全放弃 vendor 目录的,但是社区的 反馈 导致保留了对 vendor 的支持。

简单来讲,如果要支持的话,可以这样:

  • go mod vendor 会根据 go.mod 中的文件重置 vendor 目录,将依赖的包拷贝入内
  • 默认情况下, go build 会忽略 vendor 中的内容
  • 指定了 -mod=vendor 情况下才会从根目录下的 vendor 目录找包依赖,这种情况下会忽略 go.mod 的内容。 注意,只会从项目的顶级目录下找,其它目录下的会被忽略。
  • 如果希望全局支持的话,可以设置 GOFLAGS=-mod=vendor 环境变量。

所以,对于用户来讲,是不是可以考虑不再关心 vendor 目录了?

2.3. go mod 使用私有库

不使用 go mod 私有库直接手动拷贝到 $GOPATH/src 下面就可以用了,使用 go mod 之后,依赖库的位置放在了 $GOPATH/pkg/mod 下面,并且还有 go.sum 校验, 所以直接拷贝的方式不可用了,可以用下面的方法来解决。Go 使用 gitlab 私有 repo:

  1. .gitconfig 中添加:

    [url "git@gitlab.com:"]
    insteadOf = https://gitlab.com/
    
  2. GOPRIVATE="gitlab.com/c3441" go get -u gitlab.com/c3441/cbl-go@master

这两步骤缺一不可。

<2021-08-16 Mon 15:45> UPDATE

Go 1.16 之后, -insecure 参数将会被逐渐废弃,如果你使用的话,会提示 deprecated ,官方的 release log 里有说明:

The go get -insecure flag is deprecated and will be removed in a future version. This flag permits fetching from repositories and resolving custom domains using insecure schemes such as HTTP, and also bypasses module sum validation using the checksum database. To permit the use of insecure schemes, use the GOINSECURE environment variable instead. To bypass module sum validation, use GOPRIVATE or GONOSUMDB. See go help environment for details.

可以看出后续使用 GOINSECURE 环境变量来代替。相关的讨论:

2.4. go get proxy

由于众所周知的原因, go get 速度非常慢,经常 timeout。一种解决办法是自己有 VPN 设置 http.https 代理,另外一种办法是使用公共的代理。 比如:七牛提供的 https://goproxy.cn/

echo "export GO111MODULE=on" >> ~/.profile
echo "export GOPROXY=https://goproxy.cn" >> ~/.profile
source ~/.profile

另外,https://goproxy.io/zh/

Footnotes:

First created: 2019-01-18 11:07
Last updated: 2022-12-11 Sun 12:49
Power by Emacs 29.0.91 (Org mode 9.6.6)