GO 包管理机制总结

2 篇文章 0 订阅

GO 包管理机制总结

发展

go 包管理发展

GO 的包管理机制主要有三个阶段:

  1. GOPATH 模式

多个工程共享 GOPATH 目录,所有工程的公共依赖包都放在 GOPATH 对应的目录下,产生一个主要问题——随着项目的增加和依赖包越来越多,GOPATH 目录越来越臃肿,里面包含了不同项目的依赖包。当需要把项目放到别的机器上时,依赖包的混乱难以有效迁移。

  1. go vendor 模式

每个工程可以将依赖包直接放到工程子目录 vendor 中,这样不同的工程可以存放自己需要的各种依赖包到 vendor 目录中,互不影响,当工程放到其它机器上进行开发、编译时,也不在需要在花时间下载所有需要的依赖了。vendor 目录解决了工程依赖打包的问题,可将依赖与工程一起打包,减少下载依赖的时间,它同时被 “GOPATH 模式” 和 “Go Mod 模式” 支持。

go vendor 能够很好地解决 GOPATH 不同工程包混乱的问题,但是没有依赖包的版本记录,可能会造成不同机器之间依赖包版本不一致的问题,需要手动同步依赖包版本。

  1. go mod 模式

go mod 一方面解决了 GOPATH 下必须将工程放在 GOPATH 目录下的问题,另一方面解决了 go vendor 下手动导包和没有记录依赖包版本变更的问题。

在 go.mod 文件中记录了不同版本依赖包的信息,支持自动下载指定的依赖包,可以自动扫描工程依赖的包信息加入 go.mod。在 go get 依赖包后也会自动加入 go.mod ,同时 go mod 也兼容了 vendor 目录,可以使用 go mod vendor 命令自动将依赖包放在工程子目录的 vendor 目录下。go mod 对 vendor 目录的支持可以很方便的将老的 GOPATH 模式的工程转移到新的包管理工具 go mod 中。

应用

GOPATH/go vendor 模式应用

对于 golang 的工程,若没有开启 go mod,则工程必须放在 GOPATH/src 目录下,工程本身也将作为一个依赖包,可以被其它 GOPATH/src 目录下的工程引用。在有了 go vendor 模式后,vendor 目录下的文件也可以作为第三方的依赖包。当 vendor 目录和 GOPATH 目录均存在依赖包时,是如何进行选择的?

go包导入顺序

  1. 在当前目录下的 vendor 目录查找依赖的 package
  2. 当前目录不存在 vendor 目录,则去上一级目录寻找
  3. 重复步骤 2 直到进入 $GOPATH/src 目录
  4. 没有在 vendor 目录中查找到依赖包,则进入 $GOROOT 目录查找依赖包
  5. $GOROOT 目录也没有依赖包,则进入 $GOPATH 目录寻找依赖包

Go Mod 模式应用

go mod 在 1.11 版本中试验性加入 go ,在 1.13 版本后正式作为官方的包管理工具。

环境变量 GO111MODULE

go 通过环境变量 GO111MODULE 的 3 个值 off、on、auto 来决定是否使用 go mod. 这三个值影响分别如下:

  • GO111MODULE=off:关闭 go modules 功能,在编译的时候仍旧在 $GOPATH/src 或者 vendor 目录中寻找依赖。这种包管理模式为 “GOPATH 模式”。
  • GO111MODULE=on:开启 go modules 功能,在编译时不会在 $GOPATH/src 中寻找依赖。将在项目根目录生成 go.mod 文件。同时,依赖包不再存放在 $GOPATH/src 目录,而是存放在 $GOPATH/pkg/mod 目录,多个项目可以共享缓存的 modules。
  • GO111MODULE=auto:默认值,在 go v1.13 及之后版本中,如果工程目录下包含 go.mod 文件或者位于包含 go.mod 文件的目录下,则开启 go modules 功能。在 go v1.11 中 auto 值需要工程在 GOPATH/src 之外的目录中才会开启 go mod,以确保兼容性。
go mod 命令行
   // 常用命令
   go mod init        // 初始化 go.mod,将开启 mod 使用
   go mod tidy        // 添加或者删除 modules,取决于依赖的引用
   go mod vendor      // 复制依赖到 vendor 目录下
    
   // 其它命令
   go mod download  // 下载 module 到本地
   go mod edit     //  编辑 go.mod
   go mod graph    //  打印 modules 依赖图
   go mod verify   //  验证依赖
   go mod why      //  解释依赖使用

一般来说,并不需要手动修改 go.mod 文件,通过在工程里使用 go get 命令、go mod tidy 命令,都将会把依赖自动记录到 go.mod 文件中.

go mod tidy // 添加工程中使用到的 go 依赖包,并删除未使用过得依赖包.
go get github.com/repo/package@branch // 下载指定版本的 go 依赖包

go mod 和 go vendor 的区别

go vendorgo mod
项目是否需要放在 $GOPATH/src需要非必要(可放可不放)
依赖的路径vendorGOPATH/pkg/mod
包的查找顺序vendor->GOPATH/src->GOROOT/srcGOPATH/pkg/mod->GOROOT/src
依赖包的加入方式手动加入,且没有依赖包版本记录。升级更新需要手动操作在 go.mod 文件中记录了不同版本依赖包的信息,支持自动下载指定依赖包,可以自动扫描工程依赖的包信息加入 go.mod

实践

业务遇到问题

之前的项目使用 go vendor 模式,自己使用的 go 版本为 1.17,首先将 GO111MODULE 设为 off,然后将项目放入系统环境变量 GOPATH/src 下。goland 导入后报错,vscode 导入后也报错。后来发现有的包依赖另外的包,没有放到 vendor 目录下,后来将缺失的包放入 GOPATH/src 下(没有放在 vendor 目录下是为了不影响 git 记录,当然也可以通过 .gitignore 处理)。

vendor 模式下的项目导入流程:

  1. 将项目放入 $GOPATH/src 下
  2. 确保所有依赖包都在 vendor 目录下或者在 GOPATH/src 下或者在 $GOROOT/src 下

goland IDE 配置

  • 配置好 GOPATH(可采用全局默认 GOPATH)
  • 禁用 Go Modules

在这里插入图片描述

go mod 实践

# 1. 开启 GO111MODULE
export GO111MODULE=on

# 2. 创建项目目录
mkdir hello

# 3. 创建 go.mod 文件
go mod init example.com/hello

# 4. 创建项目文件(以 hello.go 为例)
package main
import (
        "fmt"
        "rsc.io/quote"
)
func main() {
        fmt.Println("go mod test start...")
        defer fmt.Println("go mod test end!")
        fmt.Println(quote.Hello())
}

# 5. 下载依赖包 
go get rsc.io/quote

# 6. go run 运行自动更新 go.mod 和 go.sum
go run hello.go

# 查看 go.mod 和 go.sum 可以看到内容已经更新

参考链接

go mod 和 go vendor 使用与区别

go 包管理 — GOPATH、vendor、go mod 机制

Go mod 的简单实践

Go Modules 的前世今生与基本使用

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值