2019年12月19日 Go生态洞察:Go模块化之旅


🌟 2019年12月19日 Go生态洞察:Go模块化之旅

摘要

🐯 猫头虎博主在此!探索Go语言世界的朋友们,今天我们将深入挖掘Go模块化的旅程。作为搜索词条的高频命中,Go的模块化进程自2018年以来引起了广泛关注。让我们一起揭开Go模块化的面纱,探索其深刻影响!

引言

Go语言作为一种高效的编程语言,在2018年进行了一次重大变革——Go模块(Go Modules)。这一变革标志着Go生态从传统的GOPATH模式转向更现代化的模块管理方式。接下来的内容将详细介绍Go模块的发展历程、特性及其对Go生态的影响。

🚀 正文

🌱 Go模块的诞生背景

2018年对Go生态来说是具有里程碑意义的一年。Go社区集中关注包管理问题,并于2月开始探讨如何将包管理直接集成到Go工具链中。8月,我们首次粗略实现了这一功能,即Go模块,并在Go 1.11中引入。这一变革是自Go 1以来,对Go生态最深远的改变。

代码语言:javascript
复制
module my/thing
go 1.11

require (
other/thing v1.0.2
new/thing v2.3.4
)

🔄 Go版本的进化

Go 1.11于2018年8月发布,初步支持模块。模块支持与传统的GOPATH机制并行存在。go命令在GOPATH/src外的目录树中运行时默认启用模块模式,根据目录中的go.mod文件标识。这个设置可以通过设置$GO111MODULE环境变量为onoff来覆盖;默认行为是auto模式。我们已经看到了模块在Go社区的显著采用,以及许多有用的建议和错误报告帮助我们改进模块。

Go 1.12计划于2019年2月发布,将细化模块支持,但默认仍处于auto模式。除了许多错误修复和其他小改进外,Go 1.12最显著的变化是,像go run x.gogo get rsc.io/2fa@v1.1.0这样的命令现在可以在GO111MODULE=on模式下运行,而无需显式的go.mod文件。

我们的目标是在2019年8月计划的Go 1.13中默认启用模块模式(即将默认值从auto更改为on),并弃用GOPATH模式。为此,我们一直在改进工具支持以及对开源模块生态系统的支持。

🛠️ 工具与IDE集成

在过去的八年中,我们已经创造了大量工具,这些工具假定Go源代码存储在GOPATH中。转向模块需要更新所有做出这种假设的代码。我们设计了一个新包golang.org/x/tools/go/packages,它抽象了查找和加载给定目标的Go源代码的操作。这个新包自动适应GOPATH和模块模式,并且也可以扩展到特定于工具的代码布局,如Bazel所使用的布局。我们一直在与Go社区的工具作者合作,帮助他们在他们的工具中采用golang.org/x/tools/go/packages。

作为这一努力的一部分,我们还在努力将各种源代码查询工具如gocode、godef和go-outline统一为一个工具,该工具可从命令行使用,并支持现代IDE使用的语言服务器协议。

模块的过渡和包加载中的变化也促使Go程序分析发生了重大变化。作为对go vet的重构以支持模块,我们引入了一个用于Go程序的增量分析的通用框架,在该框架中,分析器一次针对一个包进行调用。在这个框架中,一个包的分析可以写出事实,供导入第一个包的其他包的分析使用。例如,go vet对log包的分析确定并记录了log.Printffmt.Printf的包装器。然后go vet可以检查调用log.Printf的其他包中的printf风格格式字符串。这个框架应该能够启用许多新的、复杂的程序分析工具,帮助开发人员更早地发现错误并更好地理解代码。

📦 模块索引

go get的最初设计中最重要的部分之一是它是去中心化的:我们当时相信,今天仍然相信,任何人都应该能够在任何服务器上发布他们的代码,与Perl的CPAN、Java的Maven或Node的NPM等中心注册表形成对比。将域名放在go get导入空间的开始部分,重用了一个现有的去中心化系统,并避免了重新解决谁可以使用哪些名称的问题。它还允许公司在私有服务器上导入代码,与公共服务器上的代码并行。

我们正在开发一个新服务,Go模块索引,它将提供一个公共日志,记录进入Go生态系统的包。像godoc.org和goreportcard.com这样的网站将能够观察这个日志,以获取新条目,而不是每个独立实现代码来找到新包。我们还希望该服务允许使用简单查询查找包,以允许goimports为尚未下载到本地系统的包添加导入。

🔒 模块认证

目前,go get依赖于连接级认证(HTTPS或SSH)来检查它是否正在与正确的服务器通信以下载代码。没有对代码本身的额外检查,如果HTTPS或SSH机制以某种方式受到了影响,则存在中间人攻击的可能性。去中心化意味着构建所依赖的代码是从许多不同的服务器获取的,这意味着构建依赖于许多系统来提供正确的代码。

Go模块设计通过在每个模块中存储go.sum文件来改进代码认证;该文件列出了模块每个依赖项的预期文件树的加密散列。使用模块时,go命令使用go.sum来验证在构建中使用依赖项之前,它们是否与预期版本逐位相同。但go.sum文件只列出了该模块所使用的特定依赖项的散列。如果您正在添加新依赖项或使用go get -u更新依赖项.

模块认证的必要性 🔐

go get依赖于连接级别的认证(HTTPS或SSH)来确保下载代码的安全性。在模块设计中,通过在每个模块中存储go.sum文件来改善代码认证,该文件列出了模块依赖项的预期文件树的加密哈希。

模块镜像的作用 📡

由于go get从多个源服务器获取代码,因此代码的获取速度和可靠性受限于最慢、最不可靠的服务器。模块镜像的引入,为解决这一问题提供了新

的方案。

模块发现的进展 🔎

我们提到的模块索引将使构建像godoc.org这样的网站变得更容易。2019年的部分工作将是对godoc.org进行重大改造,使其对于需要发现可用模块的开发者更加有用。

大局观

以下图表展示了本文中讨论的设计中模块源代码的流动方式。

表格:知识要点总结

关键点

描述

Go 1.11

引入Go模块的初步实现

Go 1.12

进一步完善模块支持

工具与IDE集成

新的包以适应GOPATH和模块模式

模块索引

提供公共日志,记录新包

模块认证

通过go.sum文件提高安全性

模块镜像

提高代码获取的速度和可靠性

模块发现

重塑godoc.org,改善模块发现体验

总结

本文被猫头虎的Go生态洞察专栏收录,详情点击这里。我们深入探讨了Go模块化的起源、发展及其在Go生态中的重要性。从Go 1.11到Go 1.12,再到工具和模块认证的进步,Go的模块化之旅充满挑战与机遇。