这是一篇关于安全的技术文章

简介: 这是一篇关于安全的技术文章

前 言

In the world of software management there exists a dreaded place called “dependency hell.” The bigger your system grows and the more packages you integrate into your software, the more likely you are to find yourself, one day, in this pit of despair.

依赖管理是一个语言必须要解决的问题,而且随着项目依赖的模块量以及复杂程度不断增加会显得更加重要。Go依赖管理发展历史可以归纳如下:

goinstall(2010.02):将依赖的代码库下载到本地,并通过import引用这些库
go get(2011.12):go get代替goinstall
godep(2013.09):godep提供了一个依赖文件,记录所有依赖具体的版本和路径,编译时将依赖下载到workspace中,然后切换到指定版本,并设置GOPATH访问(解决go get没有版本管理的缺陷)
gopkg.in(2014.03):通过import路径中添加版本号来标示不同版本,而实际代码存放于github中,go通过redirect获取代码。例如(import gopkg.in/yaml.v1,实际代码地址为:https://github.com/go-yaml/yaml)
vendor(2015.06);Go 1.5版本引入vendor(类似godep),存放于项目根目录,编译时优先使用vendor目录,之后再去GOPATH,GOROOT目录查找(解决GOPATH无法管控依赖变更和丢失的问题)
dep(2016.08):dep期望统一Go依赖管理,虽然提供了兼容其它依赖管理工具的功能,但是本质上还是利用GOPATH和vendor解决依赖管理
Go Modules(2018.08):Go 1.11发布的官方依赖管理解决方案,并最终统一了Go依赖管理(by Russ Cox)。Go Modules以semantic version(语义版本化)和Minimal Version Selection, MVS(最小版本选择)为核心,相比dep更具稳定性;同时也解决了vendor代码库依赖过于庞大,造成存储浪费的问题
通过如上历史,我们可以看出:Go依赖管理的发展历史,其实就是Go去google的历史(google内部没有强烈的版本管理需求),同时也是典型的社区驱动开发的例子

接下来,我将详细探讨Go Modules的两大核心概念:semantic version(语义化版本)和Minimal Version Selection, MVS(最小版本选择)

2

原 理

●semantic version●

Go使用semantic version来标识package的版本。具体来说:

MAJOR version when you make incompatible API changes(不兼容的修改)
MINOR version when you add functionality in a backwards compatible manner(特性添加,版本兼容)
PATCH version when you make backwards compatible bug fixes(bug修复,版本兼容)

这里,只要模块的主版本号(MAJOR)不变,次版本号(MINOR)以及修订号(PATCH)的变更都不会引起破坏性的变更(breaking change)。这就要求开发人员尽可能按照semantic version发布和管理模块(实际是否遵守以及遵守的程度不能保证,参考Hyrum's Law)

●Minimal Version Selection●

A versioned Go command must decide which module versions to use in each build. I call this list of modules and versions for use in a given build the build list. For stable development, today's build list must also be tomorrow's build list. But then developers must also be allowed to change the build list: to upgrade all modules, to upgrade one module, or to downgrade one module.

The version selection problem therefore is to define the meaning of, and to give algorithms implementing, these four operations on build lists:

Construct the current build list.
Upgrade all modules to their latest versions.
Upgrade one module to a specific newer version.
Downgrade one module to a specific older version.
这里将一次构建(go build)中所依赖模块及其版本列表称为build list,对于一个稳定发展的项目,build list应该尽可能保持不变,同时也允许开发人员修改build list,比如升级或者降级依赖。而依赖管理因此也可以归纳为如下四个操作:

构建项目当前build list
升级所有依赖模块到它们的最新版本
升级某个依赖模块到指定版本
将某个依赖模块降级到指定版本
在Minimal version selection之前,Go的选择算法很简单,且提供了 2 种不同的版本选择算法,但都不正确:

第 1 种算法是 go get 的默认行为:若本地有一个版本,则使用此版本;否则下载使用最新的版本。这种模式将导致使用的版本太老:假设已经安装了B 1.1,并执行 go get 下载,那么go get 不会更新到B 1.2,这样就会导致因为B 1.1太老构建失败或有bug

第 2 种算法是 go get -u 的行为:下载并使用所有模块的最新版本。这种模式可能会因为版本太新而失败:若你运行 go get -u 来下载A依赖模块,会正确地更新到B 1.2。同时也会更新到C 1.3 和E 1.3,但这可能不是 A 想要的,因为这些版本可能未经测试,无法正常工作

这 2 种算法的构建是低保真构建(Low-Fidelity Builds):虽然都想复现模块 A 的作者所使用的构建,但这些构建都因某些不明确的原因而变得有些偏差。在详细介绍最小版本选择算法后,我们将明白为什么最小版本选择算法可以产生高保真的构建:

Minimal version selection assumes that each module declares its own dependency requirements: a list of minimum versions of other modules. Modules are assumed to follow the import compatibility rule—packages in any newer version should work as well as older ones—so a dependency requirement gives only a minimum version, never a maximum version or a list of incompatible later versions.

Then the definitions of the four operations are:

To construct the build list for a given target: start the list with the target itself, and then append each requirement's own build list. If a module appears in the list multiple times, keep only the newest version.
To upgrade all modules to their latest versions: construct the build list, but read each requirement as if it requested the latest module version.
To upgrade one module to a specific newer version: construct the non-upgrad

相关文章
|
7月前
|
5G 调度 vr&ar
5g技术的应用
5g技术的应用
274 0
|
3月前
|
智能硬件
技术与生活
本文通过探讨技术的本质,分析了它如何影响我们的生活、工作和思维方式。从历史的长河中看技术的发展,到现代科技如何塑造社会,文章试图揭示技术进步背后的深层意义,并思考我们应如何与技术和谐共存。
|
6月前
|
SQL 开发框架 .NET
技术心得:待处理(一)
技术心得:待处理(一)
31 0
|
数据采集 传感器 监控
LPWAN技术及常用场景(一)
LPWAN技术及常用场景(一)
363 0
|
监控 物联网 5G
LPWAN技术及常用场景(二)
LPWAN技术及常用场景(二)
266 0
|
芯片
光刻机技术
光刻机技术是一种半导体制造工艺中的关键技术,它通过使用光学透镜和光掩模将光束聚焦到硅片表面,从而将芯片设计中的图形转移到硅片上。这种技术在半导体制造过程中起着至关重要的作用,因为它可以精确地控制芯片上每个晶体管的位置和尺寸,从而实现芯片的高性能和低功耗。
|
安全 数据库 网络虚拟化
TVP技术(二)
TVP技术(二)
188 0
|
网络架构
数字数据网技术
数字数据网技术
|
设计模式 缓存 算法
你有技术焦虑症吗?
  从事软件编程已经长达8年之后,曾经中间有很长一段时间感觉自己的技术能力没有得到根本性提升,与那些优秀的同龄人相比,技术自卑油然而生,面对日新月息的技术变更和时不我待的岁月流逝,步入中年的我不得不变的焦虑起来。回顾自己的编程生涯,刚毕业的头几年,通过自主学习实现了编程语言的基本掌握,紧接着使用学到的技术完成各种项目,然后日复一日,有时候也会看看技术书籍,但是终究未能突破语言层而知晓技术背后的本质。而后通过长时间的摸索与交流,寻找到了一些解决技术人技术焦虑的方法,这些问题和方法更多的是一种思维方式,一种看问题的视角,希望这些建议能够让我们有所收获和思考。
228 0
|
SQL Oracle 前端开发

相关实验场景

更多