文章

go中的包管理

在看一个旧项目的时候,让把项目放到GOPATH/src 下,为了解决这个疑惑。看了一些与GOPATH相关的介绍而整理。

包管理

Go在 Go1.11后解决了包管理的相关问题。之前比较依赖GOPATHGOROOT的环境变量,因此在之前的项目中,都是放到GOPATH/src的目录下,现在比较流行的 go mod解决了很多问题。有以下特点:

  1. 一个版本只存一份:所有项目共享同一版本的包,下载一次,多处个项目都可以使用

  2. 版本隔离:不同版本可以并存

  3. ✅不再像之前一样依赖GOPATH

存储的位置由$GOMODCACHE决定

go get

在 go1.11之前的功能:

  1. 下载源码到 GOPATH

  2. 编译并安装到 $GOPATH/bin

在 go1.11+:

  1. 添加依赖到 go.mod

  2. 下载依赖(下载到了模块缓存中go env GOMODCACHE

  3. 安装二进制文件(与之前不同,现在需要使用 go install主动安装)

go getgo mod download的区别

go mod download只下载,go get下载并修改go.mod

go install

go install 与之前的旧版go get功能基本一致,是下载并安装包并安装,下载过程与现在go get一致。

当不带路径时:

  1. 安装当前目录(及子目录)的main包

  2. 可执行文件安装到 $GOBIN 或 $GOPATH/bin

带包路径时:

  1. 安装指定的远程包

  2. 可执行文件安装到 $GOBIN 或 $GOPATH/bin

go.mod及正常流程

  • download:将go.mod文件中所有标明的依赖下载到本地缓存

  • edit:编辑go.mod文件,它提供的命令行接口主要是提供给其它工具或脚本调用的。

  • init:在当前目录初始化一个 gomod 项目

  • tidy:分析项目依赖,修改go.mod,下载缺失的依赖,删除无用的依赖

  • graph:输出依赖图

  • verify:验证本地的依赖

  • why:解释为什么会依赖这些模块

  • vendor:导出项目依赖到 vendor 目录

正常项目的启动流程:

  1. go mod download下载依赖

  2. 使用go build(当入口项目)或者go build ./...(需要构建多个包的多服务项目)会按需对 download 的包进行编译

如果某个项目修改一个公用包的源码,怎么办?

  1. Go Modules 的缓存目录$GOMODCACHE是只读的,不推荐修改,修改完后完整性校验会失败。

  2. 推荐使用的方法有三种

    # 方法1:需要修改时,使用 replace 将包指向自己本地的目录
    git clone https://github.com/gin-gonic/gin ~/dev/gin-fork
    go mod edit -replace github.com/gin-gonic/gin=../gin-fork
    vim ~/dev/gin-fork/gin.go
    # 方法2: fork一个自己的仓库(略)
    # 方法3: 是用 vendor 模式
    # 1. 创建 vendor 目录
    go mod vendor
    # 2. 修改 vendor 中的代码
    vim vendor/github.com/gin-gonic/gin/gin.go
    # 3. 使用 vendor 模式
    go build -mod=vendor

许可协议:  CC BY 4.0