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

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

前 言

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

相关文章
|
4月前
|
存储 数据处理 图形学
什么是帧同步技术?
【5月更文挑战第3天】什么是帧同步技术?
149 9
|
4月前
|
缓存 NoSQL 算法
c/c++linux服务器开发技术
c/c++linux服务器开发技术
51 0
|
监控 物联网 5G
LPWAN技术及常用场景(二)
LPWAN技术及常用场景(二)
231 0
|
芯片
光刻机技术
光刻机技术是一种半导体制造工艺中的关键技术,它通过使用光学透镜和光掩模将光束聚焦到硅片表面,从而将芯片设计中的图形转移到硅片上。这种技术在半导体制造过程中起着至关重要的作用,因为它可以精确地控制芯片上每个晶体管的位置和尺寸,从而实现芯片的高性能和低功耗。
|
机器学习/深度学习 自然语言处理 搜索推荐
ChatAI技术
ChatAI作为人工智能技术的重要应用之一,正在塑造着人与机器之间的对话交流方式。借助先进的自然语言处理和机器学习算法,ChatAI可以模拟人类的语言能力,理解和回答用户的问题,并提供个性化的服务。本文将介绍ChatAI的定义、工作原理、应用领域,以及它对社会和技术的影响。
|
设计模式 缓存 算法
你有技术焦虑症吗?
  从事软件编程已经长达8年之后,曾经中间有很长一段时间感觉自己的技术能力没有得到根本性提升,与那些优秀的同龄人相比,技术自卑油然而生,面对日新月息的技术变更和时不我待的岁月流逝,步入中年的我不得不变的焦虑起来。回顾自己的编程生涯,刚毕业的头几年,通过自主学习实现了编程语言的基本掌握,紧接着使用学到的技术完成各种项目,然后日复一日,有时候也会看看技术书籍,但是终究未能突破语言层而知晓技术背后的本质。而后通过长时间的摸索与交流,寻找到了一些解决技术人技术焦虑的方法,这些问题和方法更多的是一种思维方式,一种看问题的视角,希望这些建议能够让我们有所收获和思考。
208 0
|
新零售 安全 大数据
究竟怎样的技术才算“有情有义”?
阿里巴巴集团首席风险官刘振飞,“我们一直认为,技术是有情有义的,是可以协助相关部门解决社会痛点和治理难点的。”
2641 0
|
Web App开发 算法 Linux
|
Web App开发 算法 NoSQL