go入门第三天 了解go语言是怎么解决包依赖管理问题的

解决包依赖管理包管理过程

初始go版本的GOPATH go 1.5 版本的 Vendor 以及现在 go Model

分别简述下各个阶段处理过程

GOPATH

GOPATH 处理过程

go编译构建过程中,会通过GOPATH 设置的环境地址,在环境地址目录下去自动查询go源文件依赖的第三方包是否存在,不存在则编译失败

package main

import "github.com/sirupsen/logrus"

func main() {
    logrus.Println("hello, gopath mode")
}

如上脚本执行 编译查到结果编译异常

[root@VM-16-13-centos test]# go1.15.13 build test.go
test.go:3:8: cannot find package "githup.com/sirupsen/logrus" in any of:
        /root/sdk/go1.15.13/src/githup.com/sirupsen/logrus (from $GOROOT)
        /root/go/src/githup.com/sirupsen/logrus (from $GOPATH

我们看到 编译失败原因是GOPATHA 默认是从 GOROOT 和GOPATH 中未找到 logrus 第三方依赖包的,未找到依赖包路径会编译失败

没找到依赖包的情况使用 go get githup.com/sirupsen/logru 会检查安装 对应的依赖包自动下载到对应的GOPATH 路径下

GOPATH 出现的问题
未能解决go依赖包各个版本的的兼容问题,导致程序无法正常构建
go get 下载的包只是那个时刻各个依赖包的最新主线版本,这样会给后续 Go 程序的构建带来一些问题。比如,依赖包持续演进,可能会导致不同开发者在不同时间获取和编译同一个 Go 包时,得到不同的结果,也就是不能保证可重现的构建(Reproduceable Build)
又比如,如果依赖包引入了不兼容代码,程序将无法通过编译。最后还有一点,如果依赖包因引入新代码而无法正常通过编译,并且该依赖包的作者又没用及时修复这个问题,这种错误也会传导到你的程序,导致你的程序无法通过编译。

go 1.5 版本的 Vendor

Vendor机制 处理过程

Vendor 机制通过增加vendor目录,优先使用vendor目录中得第三方依赖包 优先级别高于GOPATH,提交代码的时候需要将vendor目录也一并提交,别人拉你的项目也可以正常构建使用

要想开启 vendor 机制,你的 Go 项目必须位于 GOPATH 环境变量配置的某个路径的 src 目录下面。

Vendor机制 出现的问题
Go 项目必须放在 GOPATH 环境变量配置的路径下
庞大的 vendor 目录需要提交到代码仓库,不仅占用代码仓库空间,减慢仓库下载和更新的速度,开发者需要耗费精力管理自己的 vendor 下面的依赖包以及 依赖包版本

go Model

一个 Go Module 是一个 Go 包的集合。module 是有版本的,所以 module 下的包也就有了版本属性。这个 module 与这些包会组成一个独立的版本单元,它们一起打版本、发布和分发。

go Model 处理过程

将基于当前项目创建一个 Go Module,通常有如下几个步骤:
第一步,通过 go mod init 创建 go.mod 文件,将当前项目变为一个 Go Module;
第二步,通过 go mod tidy 命令自动更新当前 module 的依赖信息;
第三步,执行 go build,执行新 module 的构建。

package main

import "github.com/sirupsen/logrus"

func main() {
    logrus.Println("hello, gopath mode")
}

直接go build编译 如果没有创建 go model 汇编出错

PS D:\coder\goprojects\webtest> go build .\main.go
main.go:3:8: no required module provides package github.com/sirupsen/logrus: go.mod file not found in current directory or any parent directory; see 'go help modules'
        go mod tidy

第一步,通过 go mod init 创建 go.mod 文件
PS D:\coder\goprojects\webtest> go mod init github.com/bigwhite/module-mode
go: creating new go.mod: module github.com/bigwhite/module-mode
go: to add module requirements and sums:
        go mod tidy
第二步,通过 go mod tidy 命令自动更新当前 module 的依赖信息;
PS D:\coder\goprojects\webtest> go mod tidy
go: finding module for package github.com/sirupsen/logrus
go: downloading github.com/sirupsen/logrus v1.9.0
go: found github.com/sirupsen/logrus in github.com/sirupsen/logrus v1.9.0
go: downloading golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8
go: downloading github.com/stretchr/testify v1.7.0
go: downloading gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c

第三步,继续编译构建
PS D:\coder\goprojects\webtest> go build
PS D:\coder\goprojects\webtest> go build .\main.go
PS D:\coder\goprojects\webtest> .\main.exe
time="2022-11-25T16:34:07+08:00" level=info msg="hello, gopath mode"

深入 Go Module 构建模式

Go 语言设计者在设计 Go Module 构建模式,来解决“包依赖管理”的问题时,进行了几项创新,这其中就包括语义导入版本 (Semantic Import Versioning),以及和其他主流语言不同的最小版本选择 (Minimal Version Selection) 等机制。只要你深入理解了这些机制,你就能真正掌握 Go Module 构建模式。

语义导入版本 (Semantic Import Versioning)
语义导入版本介绍

vX.Y.Z
v 版本号前缀,版本号前缀为 1 或0时 默认不会显示 版本号前缀大于1时 v+当前的版本号代表 版本号前缀 2 则为v2
X 主版本号
Y 此版本号
Z 补丁版本号

Go Module 规定:如果同一个包的新旧版本是兼容的,那么它们的包导入路径应该是相同的
比如使用1.7.0 和1.8.0 版本 使用相同的路径如下

import "github.com/sirupsen/logrus"

要使用2.0.0版本

import "github.com/sirupsen/logrus/v2"

1.7.0 和 2.0.0 版本同时依赖使用

import (
	"github.com/sirupsen/logrus"
	logv2 "github.com/sirupsen/logrus/v2"
	 
)
最小版本选择 (Minimal Version Selection) 等机制

A 明明说只要求 C v1.1.0,B 明明说只要求 C v1.3.0 C的最新版本为 v1.7.0, go会选择使用 v1.3.0

Go 设计者另辟蹊径,在诸多兼容性版本间,他们不光要考虑最新最大的稳定与安全,还要尊重各个 module 的述求:A 明明说只要求 C v1.1.0,B 明明说只要求 C v1.3.0。所以 Go 会在该项目依赖项的所有版本中,选出符合项目整体要求的“最小版本”。

好记性不如烂笔头,本文学自 极客时间 Tony Bai · Go 语言第一课

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值