Go语言之父:开源14年,Go不止是编程语言,究竟做对了哪些?

提及编程语言,2023 年,除了老牌的 C++ 和新晋之秀 Rust 热度最高之外,就要数 Go 了。 从 2009 年由 C 语言获取灵感而发布,到如今风靡已久的高性能语言,Go 已经走过了 14 个年头。

“Go是一个项目,不只是一门语言。我们最初的目标不是创建一种新的编程语言,而是创建一种更好的软件编写方式。”

2023 年 11 月 10 日是 Go 作为开源项目推出 14 周年。Go语言之父 Rob Pike 在在悉尼 GopherConAU 会议上进行了一场耐人寻味的演讲。Go走到今天,做对了什么?做错了什么?这里总结在此,以飨诸君。

一、我们做对了什么,做错了什么 

今天是 2023 年 11 月 10 日,Go 作为开源项目推出 14 周年。2009年的这天,加州时间下午 3 点(如果没记错的话),Ken Thompson、Robert Griesemer、Russ Cox、Ian Taylor、Adam Langley、Jini Kim 和我满怀期待地看着网站上线,全世界都知道了我们在做什么。

图片

Go是一个项目,不只是一门语言。

即使是最成功的项目 ,经过反思,也有一些可以做得更好的地方。当然 ,事后看来,这些事情似乎是他们成功的关键。

这些因素正是我们想要解决的:构建现代服务器软件的复杂性:控制依赖性、与人员不断变化的大型团队一起编程、易于维护、高效测试、多核 CPU 和网络的有效使用等等。 

根据大家的反馈看,认为 Go 做错的事情都在语言层面, 而其实Go做对的事情,都在更大的故事中,即围绕语言的周边工具和生态, 比如 gofmt 以及部署和测试。这说明Go成员们做对了。 

二、Go哪里做对了?

Go为什么会取得现在的成功?总结了有以下几点。每一个都至关重要。

1.规范说明

我们从正式的规范开始。这不仅可以在编写编译器时锁定行为,还可以使 多个实现共存并就该行为达成一致。编译器本身并不是一个规范。您测试编译器的依据是什么?

2.多种实现方式

有多个编译器,它们都实现相同的规范。有了规范就可以更容易地实现这一点。

有一天,伊恩·泰勒(Ian Taylor)发邮件通知我们,在阅读了我们的规范草案后,他自己编写了一个编译器,这让我们感到惊讶。

图片

我的一位同事向我指出了 http://.../go_lang.html 。 它看起来是一种有趣的语言,我拼凑了一个 gcc前端。 当然,它缺少很多功能,但它确实在网页上编译了素数筛代码。

这是令人兴奋的,但更多的事情也随之而来,所有这些都因正式规范的存在而成为可能。

拥有多个编译器帮助我们改进了语言并完善了规范,并为那些不太喜欢我们类似 Plan-9 的业务方式的其他人提供了替代环境。

如今有很多兼容的实现,这很棒。

3.便携性

我们使交叉编译变得微不足道,这使得程序员可以在他们喜欢的任何平台上工作,并交付到任何需要的平台。 人们很容易将编译器视为是与运行的本机是原生的。Go可以打破这个假设,对许多开发者来说都是新闻。

图片

4.兼容性

我们努力使语言成型1.0 版本,然后通过兼容性保证将其锁定。Go的受欢迎程度已经很高,在一个几乎没有其他东西是稳定的世界中,不用担心新的 Go 版本会破坏你的项目,是最让人心安的。当然,很多其他项目不会这么做,因为维护强大的兼容性是需要成本的。

图片

5.库

库的发展有点偶然。一开始可以安装 Go 代码的地方非常贫瘠,但这样一个可靠、制作精良的库的存在,其中包含编写 21 世纪服务器代码所需的大部分内容,是一项重要资产。它让社区所有人都使用同一个工具包,直到我们有足够的经验来了解还应该提供什么。这非常有效,有助于防止变体库的出现,有助于统一社区。

6.工具

我们确保该语言易于解析,从而支持工具构建。起初我们认为我们需要一个适用于 Go 的 IDE,但拥有简单的工具反而会意味着,IDE 迟早将出现在 Go 上。这些工具和 gopls 一起就做到了,而且他们非常棒。

我们还为编译器提供了一套辅助工具,例如 自动化测试、覆盖率和代码审查。当然还有 go 命令,它集成了整个构建过程,并且是许多项目构建和维护 Go 代码所需的全部内容。

此外,Go 获得了快速构建的声誉。

7.gofmt 

我将 gofmt 作为一个单独的项目从工具中拿出来,因为 它不仅给Go,而且给整个编程社区上都带来了新的活力。在 Robert 编写 gofmt 之前,自动格式化程序的质量不高,因此大多未使用。

Gofmt 表明它可以做得很好,今天几乎每种值得使用的语言都有一个标准格式化程序。不争论空格和换行符所节省的时间值得花在定义标准格式和编写这段相当困难的代码以实现自动化上的所有时间。

此外,gofmt 还使无数其他工具成为可能,例如简化器、分析器甚至代码覆盖率工具。因为 gofmt 的内容成为了任何人都可以使用的库,所以您可以解析程序、编辑 AST,然后打印字节完美的输出,供人类和机器使用。

三、Go 哪里做错了?

1.并发成就了Go,但Go有责任做好指导 

并发性成就了 Go,它让Go看起来像是一种新事物。Go 对并发的支持是一个主要的吸引因素,提高了Go的早期采用率。同时,Go 的诞生在一定程度上让并发编程成为了一种主流思想,它让编程世界相信并发是一个强大的工具(特别是在多核网络世界中)方面发挥了重要作用,并且它可以比 pthread 做得更好。现在大多数主流语言都对并发有很好的支持。

更有意思的是,Go 版本的并发,非常新颖。没有协程,没有任务,没有线程,没有名称,只有 goroutine。我们发明了“goroutine”这个词,因为没有合适的现有术语。直到今天我还是希望 Unix 的拼写命令能够学会它。

问题来了,这就是我们犯了两个重大错误的地方。 

首先,并发很有趣,但我们想到的用例主要是服务器的东西,也就意味着在 net/http 等关键库中完成,而不是在每个程序中随处可见。因此,当许多程序员使用它时,他们很难弄清楚它如何真正帮助到他们。

我们应该预先解释声明一下,该语言中的并发支持真正带来的是更简单的服务器软件。这个问题就在于许多人都认为重要,但并不是对所有尝试过 Go 的人来说都很重要。“缺乏响应的指导是我们的责任。”    

第二点就是,我们花了太长时间来澄清并行性(支持多核机器上并行的多个计算)和并发性(这是一种构造代码以实现这一点的方法)之间的区别。

无数程序员试图通过使用 goroutine 并行化来提高代码速度,但常常对由此产生的速度减慢感到困惑。如果底层问题本质上是并行的,比如处理 HTTP 请求,那么并行代码只会在并行化时运行得更快。我们在解释这一点上做得很糟糕,结果让许多程序员感到困惑,并可能赶走了一些程序员。

为了解决这个问题,2012 年,我在 Heroku 的 Waza 开发者大会上发表了演讲 ,名为“并发不是并行”。这是一个有趣的演讲,但应该早点发生。

对此表示歉意。但好处仍然存在:Go 帮助普及了并发性作为构建服务器软件的一种方式。

2.接口

我认为接口是 Go 中设计得最好的东西之一。而且很明显,接口和并发性是 Go 中的一个独特的想法。它们是 Go 对面向对象设计的回答,采用原始的、以行为为中心的风格,尽管新来者不断推动结构体承载这种负载。

使接口动态化,无需提前宣布哪些类型实现它们,这困扰了一些早期的批评者,并且仍然激怒了一些人,但这对于 Go 所培育的编程风格很重要。标准库的大部分内容都是 建立在它们的基础上的,而更广泛的主题(例如测试 和管理依赖项)在很大程度上依赖于它们慷慨的“ 欢迎所有人”的性质。  

这里有一个故事要讲。在罗伯特和我办公室的那个著名的第一天,我们问了一个问题:如何处理多态性。Ken 和我从 C 语言中知道 qsort 可以作为一个困难的测试用例,因此我们三个开始讨论我们的“胚胎语言”如何实现类型安全的排序例程。

罗伯特和我几乎同时提出了相同的想法:使用类型上的方法来提供排序所需的操作。这个概念很快就发展成为这样的想法:值类型具有行为,定义为方法,并且方法集可以提供函数可以操作的接口。Go 的接口几乎立刻就出现了。 

这是经常被忽视的事情:Go 的排序是作为在接口上运行的函数实现的。这不是 大多数人熟悉的面向对象编程风格 ,但它是一个非常强大的想法。

当 Russ 加入时,他很快就指出了 I/O 如何完美地融入这个想法,并且库的发展很快,很大程度上基于三个著名的接口:empty、Writer 和 Reader,平均持有三分之二的数据、各一个方法。  这些微小的方法是 Go 的惯用方法,而且无处不在。

接口的工作方式不仅成为 Go 的显著特征,还成为我们思考库、通用性和组合的方式。这是令人兴奋的事情。但问题就产生在这里。你看,我们走这条路,很大一部分原因是我们经常看到泛型编程鼓励一种这样一种思维方式:倾向于关注类型而不是算法、关注早期的抽象而不是有机设计、关注容器而不是函数。

我们用语言本身定义了通用容器——映射、切片、数组、通道——但没有让程序员访问它们所包含的通用性。这可以说是一个错误。虽然这些类型可以很好地处理大多数简单的编程任务。但让人感到困扰的是,语言提供的内容和用户可以控制的内容之间存在障碍。

简而言之,这种思维方式陈年已久,我们花了十多年的时间才纠正过来。Ian Taylor 从一开始就敦促我们面对这个问题,但考虑到接口作为 Go 编程的基石,这很难做到。

批评者经常抱怨我们应该只做泛型,因为它们 很“简单”,也许它们可以用在某些语言中,但接口的存在意味着任何新形式的多态性都必须考虑它们。找到一种与该语言的其余部分良好配合的前进方式需要多次尝试、几次中止的实现以及数小时、数天和数周的讨论。

最终我们请来了一些由 Phil Wadler 领导的类型理论家来帮忙。即使在今天,语言中已经有了可靠的通用模型,但接口作为方法集的存在仍然存在一些挥之不去的问题。

如您所知,最终的答案是设计一个接口的泛化,可以吸收更多形式的多态性,从“方法集”过渡到“类型集”。这是一个微妙但意义深远的举措,大多数社区似乎都同意这一举措,但我的怀疑态度并未打消。

有时要花很多年的时间才能搞清楚一件事,甚至搞清楚“自己原来没太搞清楚”这件事。然后继续前进。

顺便说一句,我希望我们有一个比“泛型”更好的术语,它起源于一种不同的、以数据结构为中心的多态性风格。“参数多态性”是 Go 提供的内容的正确术语,但它有些拗口。但我们平时提“泛型”,但也不太准确。

3.对于开源项目的管理挑战与教训

要想成功,Go 必须是一个开源项目。但在我们弄清楚关键想法并进行有效实施之前,私下开发会更有成效。因此,前两年我们需要这个过程不受干扰。

向开源的过渡是一个巨大的变化,而且具有教育意义。社区的投入是巨大的。与社区互动需要花费大量的时间和精力,尤其是对于 Ian 来说,他竟然还能抽出时间来回答任何人提出的每个问题。但它带来了更多。我仍然对 Windows 移植的速度如此之快感到惊讶,这完全是由社区在 Alex Brainman 的指导下完成的。

我们花了很长时间才理解转向开源项目的含义以及如何管理它。我们说服了支持我们的社区,坚持通过强制代码审查和对细节的全面关注来保持高代码质量,而不是采用快速接受代码并在提交后进行清理的方式。这种做法将更多的工作推回给社区,需要他们了解其价值,否则他们不会感到受到应有的欢迎。

图片

有一个历史细节并不广为人知。该项目有 4 个不同的内容管理系统:SVN、Perforce、Mercurial 和 Git。感谢Russ为项目所做的历史内容管理系统的维护工作。

此外,Go语言项目是独立于Goole之外的,尽管Google提供了支持,但核心团队是独立的,没有设定议程。Google 拥有庞大的内部 Go 代码库,团队用它来测试和验证版本,但这是通过从公共存储库导入 Google 来完成的。

4.包管理

Go语言的包管理开发过程做得并不好,关键在于使用纯字符串来指定导入语句中的路径,虽然提供了灵活性,但也带来了很多问题。

Go核心团队在早期缺乏处理具有大量包版本的包管理器以及解决依赖关系图等复杂问题的经验。尽管如此,我们仍然试图让社区参与解决依赖管理问题,但最终设计出来时,许多社区成员感到被轻视。

图片

这次失败给团队上了一课,让我们更加了解如何真正与社区互动。尽管道路崎岖不平,但现在事情已经得到了解决,出现的设计在技术上非常出色,并且对大多数用户来说效果很好。

四、写在最后:Go 做到了

推出 14 年后,我们最后成功了。总的来说,很大程度上是因为最初把设计和开发 Go 作为一种编写软件的方式(而不仅仅是作为一种编程语言)这项决定,才带领我们来到了这样一个新地方。

我们到达这里的部分原因是:

  • 一个强大的标准库,可实现服务器代码所需的大部分基础知识
  • 并发性作为该语言的首要组成部分
  • 基于组合而不是继承的方法
  • 澄清依赖管理的打包模型
  • 集成的快速构建和测试工具
  • 严格一致的格式
  • 注重可读性而非聪明性
  • 兼容性保证

最重要的是,得益于令人难以置信的、乐于助人、且多元化的 Gophers 社区的支持。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/601687.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于ssm的智慧社区电子商务系统+vue论文

目 录 目 录 I 摘 要 III ABSTRACT IV 1 绪论 1 1.1 课题背景 1 1.2 研究现状 1 1.3 研究内容 2 2 系统开发环境 3 2.1 vue技术 3 2.2 JAVA技术 3 2.3 MYSQL数据库 3 2.4 B/S结构 4 2.5 SSM框架技术 4 3 系统分析 5 3.1 可行性分析 5 3.1.1 技术可行性 5 3.1.2 操作可行性 5 3…

HTML5大作业-精致版个人博客空间模板源码

文章目录 1.设计来源1.1 博客主页界面1.2 博主信息界面1.3 我的文章界面1.4 我的相册界面1.5 我的工具界面1.6 我的源码界面1.7 我的日记界面1.8 我的留言板界面1.9 联系博主界面 2.演示效果和结构及源码2.1 效果演示2.2 目录结构2.3 源代码 源码下载 作者:xcLeigh …

在MS中基于perl脚本实现氢键统计

氢原子与电负性大的原子X以共价键结合,若与电负性大、半径小的原子Y(O F N等)接近,在X与Y之间以氢为媒介,生成X-H…Y形式的一种特殊的分子间或分子内相互作用,称为氢键。 氢键通常是物质在液态时形成的&…

第1章 线性回归

一、基本概念 1、线性模型 2、线性模型可以看成:单层的神经网络 输入维度:d 输出维度:1 每个箭头代表权重 一个输入层,一个输出层 单层神经网络:带权重的层为1(将权重和输入层放在一起) 3、…

数据库设计——DML

D M L \huge{DML} DML DML:数据库操作语言,用来对数据库中的数据进行增删改查。 增(INSERT) 使用insert来向数据库中增加数据。 示例: -- DML : 数据操作语言 -- DML : 插入数据 - insert -- 1. 为 tb_emp 表的 us…

Kubernetes二进制部署 单节点

一、环境准备 k8s集群master1:192.168.229.90 kube-apiserver kube-controller-manager kube-scheduler etcd k8s集群node1: 192.168.229.80 kubelet kube-proxy docker flannel k8s集群node2: 192.168.229.70 kubelet kube-proxy docker flannel 至少2C2G 常见的k…

Flutter3.X基础入门教程(2024完整版)

Flutter介绍: Flutter是谷歌公司开发的一款开源、免费的UI框架,可以让我们快速的在Android和iOS上构建高质量App。它最大的特点就是跨平台、以及高性能。 目前Flutter已经支持 iOS、Android、Web、Windows、macOS、Linux的跨平台开发。 教程所讲内容支持…

独立式键盘控制步进电机实验

#include<reg51.h> //包含51单片机寄存器定义的头文件 sbit S1P1^4; //将S1位定义为P1.4引脚 sbit S2P1^5; //将S2位定义为P1.5引脚 sbit S3P1^6; //将S3位定义为P1.6引脚 unsigned char keyval; //储存按键值 unsigned char ID; …

bat批处理文件_命令汇总(2)

文章目录 1、换行2、返回上一级目录cd..3、隐藏指令回显echo off4、开启指令回显echo on5、用关闭echo off指令本身的回显6、echo提示信息 1、换行 cd.. echo. echo. echo. pause2、返回上一级目录cd… 3、隐藏指令回显echo off echo off echo hello1 echo hello2 pause4、开…

tomcat session cookie值设置逻辑

tomcat session cookie 值设置&#xff0c;tomcat jsessionid设置 ##调用request.getSession() Controller RequestMapping("/cookie") public class CookieController {RequestMapping("/tomcatRequest")ResponseBodypublic String tomcatRequest(HttpS…

软件测试|什么是Python构造方法,构造方法如何使用?

构造方法&#xff08;Constructor&#xff09;是面向对象编程中的重要概念&#xff0c;它在创建对象时用于初始化对象的实例变量。在Python中&#xff0c;构造方法是通过特殊的名称__init__()来定义的。本文将介绍Python构造方法的基本概念、语法和用法。 什么是构造方法&…

轻松获取CHATGPT API:免费、无验证、带实例

免费获取和使用ChatGPT API的方法 快速开始&#xff1a;视频教程 章节一&#xff1a;GPT-API-Free开源项目介绍 GPT-API-Free 是一个开源项目&#xff0c;它提供了一个中转API KEY&#xff0c;使用户能够调用多个GPT模型&#xff0c;包括gpt-3.5-turbo、embedding和gpt-4。这…

记一次服务器被入侵的排查过程

起因 阿里云安全中心报告了告警信息&#xff0c;同时手机短信、邮件、电话也接收到了来自阿里云的风险通知&#xff0c;感觉这方面阿里云还是不错。 排查及解决过程 这条wget指令究竟是怎么被运行的 我无法定位到攻击人员是通过什么样的方式让我的java程序执行了wget这条指…

地平面--高速布线

https://baijiahao.baidu.com/s?id1764139038516816855&wfrspider&forpc 概念 回顾传输线&#xff0c;由任意两条有一定长度的导线组成&#xff0c;一条为信号路径&#xff0c;一条为返回路径。基本电路理论告诉我们&#xff0c;信号是由电流传播的&#xff0c;明确的…

ECMAScript简介及特性

ECMAScript&#xff0c;通常简称为ES&#xff0c;是一种由ECMA&#xff08;欧洲计算机协会&#xff09;国际组织标准化和推动的脚本语言规范。它被广泛用于Web浏览器和服务器端编程&#xff0c;是JavaScript的基础。 ECMAScript的起源可以追溯到1996年&#xff0c;当时Netscape…

vue2 消息弹框

父页面 <template><div style"margin-top: 20px"><div class"nav-style msg-style"><el-badge :value"value" :max"99" class"num" v-if"value > 0"><i class"el-icon-bell&…

深度生成模型之图像翻译GAN ->(个人学习记录笔记)

文章目录 深度生成模型之图像翻译GAN图像翻译的应用1. 风格迁移2. 数据增强3. 经典图像任务4. 内容创作5. 人脸图像编辑6. 人体图像编辑 图像翻译模型1. 有监督图像翻译模型2. 无监督图像翻译模型3. 多域图像翻译模型 深度生成模型之图像翻译GAN 图像翻译的应用 1. 风格迁移 …

8、VS中Git使用

VS中Git使用 1.基础操作1.1 VS配置Git1.2 操作界面 2.本地库版本管理2.1 创建管理本地库2.2 暂存、存储2.3 提交2.4 版本切换 3.分支操作3.1 分支应用3.2 新建分支3.3 合并分支、解决冲突3.4 删除分支 4.远程库版本管理4.1 新建、克隆4.2 提取、拉取、推送与同步4.3 团队开发 最…

深入Pandas(二):高级数据处理技巧

文章目录 系列文章目录引言时间序列分析可视化示例 高级数据分析技术分组与聚合操作时间序列分析 高级数据操作数据合并与重塑示例&#xff1a;数据合并merge示例&#xff1a;数据合并concat示例&#xff1a;数据重塑 - 透视表 高级索引技巧 结论 系列文章目录 Python数据分析…

30、共空间模式CSP与白化矩阵

CSP算法和PCA降维都涉及到了白化&#xff0c;那白化的目的和作用到底是啥呢&#xff1f; 矩阵白化目的&#xff1a; 对于任意一个矩阵X&#xff0c;对其求协方差&#xff0c;得到的协方差矩阵cov(X)并不一定是一个单位阵。 下面介绍几个线代矩阵的几个概念&#xff1a; 1、…