标签 Cpp 下的文章

Go语言的遗产

本文是gohugo作者Steve Francia在意大利佛罗伦萨举办的GoLab上分享的闭幕演讲讲稿的文字版,该演讲的主题为”Go的遗产”。该演讲讨论了Go语言继承的遗产,以及它是如何尊重这些遗产的,并在最后总结了Go希望留给后来者的遗产。

img{512x368}

演讲胶片

我们有责任保留好留给我们的遗产,并留下值得我们子孙后代继承的遗产 – 克里斯汀·格雷格(Christine Gregoire)

1. Go语言之前

img{512x368}

1950年

在1950年代后期,人们对每台新计算机如何产生自己独特的语言而感到不安。当时,编程语言是由硬件制造商提供的,并且因型号而异。跨计算机且保持一致的第一门编程语言是Fortran,但这仍然仅适用于其制造商IBM(生产的计算机)。而后,人们成立了一个委员会,该委员会的使命就是设计第一种真正通用的、独立于机器的编程语言。

img{512x368}
图:编程语言历史Babel塔,CACM封面,1961年1月

1960年

1960年1月,有13位计算机科学家在巴黎举行了一次空前的会议,旨在(设计)开发出这样一种语言。美国派出了6位代表,欧洲派出了7位代表。

会议上无休止、令人振奋的讨论也让科学家们筋疲力尽。当一个人的好主意与他人的坏主意一起被抛弃时,一个人就会变得更加恼火。然而,在整个会议期间内,大家都没有懈怠,持续地努力投入着。

最终这13名科学家的思想碰撞产生了良好的化学反应 – Alan Perlis

Algol

img{512x368}

这是一种远远超越其时代的语言,它不仅是对其前辈的一种改进,而且对其所有后继者也产生了重大影响。- Tony Hoare关于编程语言设计的提示– 1973年

img{512x368}

之后,原本一脉相承的语言出现了分裂:

  • Pascal这一分支在欧洲蓬勃发展,有许多继任者,包括ModulaOberon

img{512x368}

  • C语言在美国激增,激发和促进了C++、C#、Java以及JavaScript、Python、Perl、PHP和许多其他语言的诞生和发展。

img{512x368}

  • 到2007年,存在的数十种编程语言都可以追溯到其共同祖先:Algol。

img{512x368}

1964年

我们的并发故事始于Doug McIlroy,他在1964年提出了一些新的想法,这些想法最终演化为Unix Pipes。

当有必要以另一种方式处理数据时,我们应该有一些耦合程序的方法,例如像将花园软管拧入另一部分那样。这也是IO的方式。- Doug McIlroy

背后故事

在1970年至1972年的一段时间内,我不时说:“如何做这样的事情?”,然后我提出了另一个建议,另一个建议,另一个建议。有一天,我想出了一种shell语法用于支持管道使用,Ken说:“我要去实现它!”他厌倦了听到所有这些内容……[并且]他说,“要去实现它”。他没有完全按照我为管道系统调用所建议的去做。他发明了一种更好一点的东西,终于又改变了今天的样子。他在一夜之间将管道符放入了Unix(并且他做到了)……。

麦克罗伊(McIlroy)引述:布赖恩(Brian)的墙上还挂着一张纸,在那张纸上我谈到了像花园软管那样将流(stream)拧在一起。所以这个想法在我脑海中徘徊了很长时间。

同时,在Thompson和Ritchie在黑板上,草拟了一个文件系统,我正在草拟如何在黑板上进行数据处理,方法是将一系列过程串联在一起,并寻找一种将过程连接在一起的前缀表示法语言。之所以失败,是因为很容易说出“cat into grep into……”或“who into cat into grep”等等。这么说很容易,而且从一开始就很清楚,这就是您想说的。但是这些命令具有所有这些附带的参数。它们不仅具有输入和输出参数,还具有选项,并且在语法上还不清楚如何将这些选项插入以前缀表示法编写的链中,比如:cat(grep(who …))。在句法上很多人不知道如何做。所以我把这些非常漂亮的程序写在黑板上,用的语言不够强大,无法应付现实。因此,我们实际上并未这样做。

1978年

到1978年,在对多处理器进行编程的背景下,有许多提议的方法被用于通信和同步。共享内存是最常见的通信机制。

托尼·霍尔(Tony Hoare)发表了一篇论文,该论文改变了一切。它比时代提前了几十年。他称他的论文为:”通讯顺序进程,communicating sequential processes”,就是大家熟知的CSP。

img{512x368}

  • 进程(Processes):执行单元
  • 顺序(Sequential):每个进程都作为一个普通的单线程程序运行
  • 通讯(Communicating):进程如何协调
  • 没有内存共享
  • 没有线程,没有互斥体

Hoare的论文提出了一种语言,每个进程(或者作为一个普通的单线程程序)按顺序执行,通过无缓冲通道(unbuffered channel)相互通信。Hoare的通信进程比典型的Unix Shell管道更通用,因为它们可以以任意模式连接。

img{512x368}

三个语言分支因Hoare的CSP论文而诞生:ErlangOccamNewsqueak

  • 1983年诞生的Occam最接近CSP论文(由Hoare推荐)
  • Erlang在80年代后期专注于CSP的功能方面,并使用mailbox在进程之间进行通信
  • Rob Pike(Newsqueak之父)追逐了并发白鲸(the concurrency white whale)长达20年

img{512x368}

Go是第一种可以同时拥有欧洲和美国语言设计分支传统的语言。实际上,它已经统一了这三个分支

2016年,黑客新闻评论(Hacker News)上的一则帖子称Go语言时停留在70年代的一种语言,这引起了一些对Go的批评……

2. 对过去伟大思想的复兴

img{512x368}

编程语言发展的四波浪潮

img{512x368}

  • 第一波浪潮:语言扩张 – 巴别塔

特征:多样化。很久以前,语言是多种多样的,并在在思想、方法和意见等方面体现出多样性。

  • 第二波浪潮:语言的标准化

特征:快速、复杂且对开发不友好。语言的标准化发生了数十年。到2000年代,事情开始停滞。他们融合为两个阵营:Java/JVM和C/CLR。C++、Java、C#都非常相似。

  • 第三波浪潮:脚本语言

特征:慢、不安全但对开发友好。脚本语言作为对上述语言的复杂性和痛苦的回应而应运而生。它们开发快速而松散,对开发人员友好,但缺乏性能和安全性。

  • 第四波浪潮:恢复

特征:快速、安全、对开发人员友好

Go是对这些语言的复杂性和痛苦的一种反应,也是对脚本语言快速开发和松散本质的反应。

Go恢复了早期语言的简单性和灵活性,增加了现代语言的安全性和开发友好性。Go以一种非常真实的方式复兴了许多伟大的想法,这些想法终于准备就绪。

Go给人的感觉就像是来自60年代,70年代,80年代,90年代,00s,10年代的语言……Steve Francia 2019

Go感觉像这样是因为它由过去60年来的许多伟大构想组成。

img{512x368}

现在,我想谈谈Go中的3种特定功能(简单、并发和Go的OO)以及这些思想起源的4种语言(Oberon、Newsqueak、Simula和Smalltalk)。在Go恢复它们之前,许多思想被遗忘了。

1988年

简单易读的结构和语法: Oberon&C

Niklaus Wirth负责Algol-W,Pascal,Modula。现在是1988年,他的最新语言是Oberon

Oberon的程序结构,以“hello, world”例子为例:

MODULE hello;

IMPORT Out;

BEGIN
    Out.String("Hello, World"); Out.Ln
END hello.

Oberon围绕着爱因斯坦(Albert Einstein)的座右铭设计:“使事情尽可能简单,但不要过于简单。”

程序结构非常简单。

下面是Go的”hello world”程序结构:

package main

import "fmt"

func main(){
    fmt.Println"hello world")
}

这个例子看起来应该很熟悉,它直接采用Oberon的结构。

我们再来看看Oberon的声明结构

CONST n = 42;
TYPE mystring = ARRAY 32 OF CHAR;
VAR s: mystring;

PROCEDURE squared(x:INTEGER):INTEGER;
BEGIN
    RETURN x * x
END squared;
VAR b,c: INTEGER = 1,2;

再来看看Go的声明结构:

const n = 42

type mystring string

var s mystring

func squared(x int) int {
    return x*x
}

var b, c int = 1, 2

在Go和Oberon中,声明都是从左到右(名称,类型,可选值),这恰与C相反,在C语言中,类型放在前面。

很多人看到Go后会问为什么我们要翻转C语法,他们错误地认为Go的声明结构来自C语言。它不是,它来自Oberon。

Go使用了Oberon形态,但却用C的token:

  • {}代替BEGIN END
  • ++,– 代替(内置)的INC和DEC
  • != 代替#
  • %代替MOD
  • || 代替OR
  • []代替ARRAY
  • 结构体代替RECORD
  • *代替POINTER TO

虽然结构来自Oberon,但Go使用的token却来自C。

  • 这里没有太多,这就是重点。语法和结构都很简单。
  • 没有继承,没有层次。没有复杂的作用域(scope)系统。
  • 它们尽可能简单,但并不过于简单。

您可以看到Go如何采用Oberon的简单结构,但是删除了笨拙的语法,并采用C语言的更加优雅和熟悉的语法替换了它们。

这样做的结果是一种非常易读的语言诞生了。

1989年

并发与Newsqueak

罗伯·派克(Rob Pike),他于1989年在贝尔实验室工作。他在这里设计了Newsqueak

  • Newsqueak是一门用于研究和探索的编程语言
  • 它致力于在Sequeak基础上添加实用的、切实可行的并发(concurrency)支持
  • Newsqueak语法上类似C
  • 像CSP一样,Newsqueak使用Channel作为Process的集合点

Rob Pike的Newsqueak在语法上看起来像C,但对并发支持的更好。Squeak用于设计菜单和滚动条之类的设备,Newsqueak解决了同样的问题,但涉及范围更广:Newsqueak用于编写整个应用程序,尤其是窗口系统。

Newsqueak-Prime Sieve pt.1

译注:Rob Pike拿手的素数筛例子

counter := prog(end: int, c: chan of int) {
    i: int;
    for(i = 2; i<end; i++) c<-=i;
};

filter := prog(prime: int, listen, send: chan of int) {
    i: int;
    for(;;)
        if((i=<-listen)%prime)
            send<-=i;
};

Newsqueak-Prime Sieve pt.2

sieve := prog(c: chan of int) {
    for(;;) {
        prime := <-c;
        print(prime, “ “);
        newc := mk(chan of int);
        begin filter(prime, c, newc);
        c = newc;
    }
};

count := mk(chan of int);

begin counter(10000, count);
sieve(count);

与CSP和Squeak不同,Newsqueak将channel视为一等公民:channel可以存储在变量中,可以作为参数传递给函数,甚至channel自身也可以通过channel发送。

另外”<-c(receive)”表达式也是第一次在这里介绍。

channel和routine

Go:

c := make(chan int)
c <- 1
x = <-c
go f(x)

vs.

Newsqueak:

c := mk(chan of int);
c <- = 1;
x = <-c;
begin f(x);

我们看到:Go的并发方法几乎与Newsqueak完全相同,channel和 goroutines的使用方式也是相同的。

select

Newsqueak还使用了看起来与Go的select语句非常相似的select。

select {
    case msg1 = <-c1:
        print(“received”, msg1, “\n”);
    case msg2 = <-c2:
        print(“received”, msg2, “\n”);
}

您可以清楚地看到Go并发的基础在25年前是如何在Newqueak中被建立起来的。Go采纳了这些”老想法”,并对其进行了改进,使其可以投入生产。

Ryan Dahl: Node.js的创建者的访谈(2017)

我喜欢Go的编程模型。使用goroutine是如此简单和有趣……如果您要构建服务器,那么我无法想象使用Go以外的任何工具。Goroutine使Go的并发变得简单。

1965年

面向对象基础(Smalltalk)

OO在C++/Java之前就已存在,在C++和Java重新定义面向对象之前。

什么是面向对象?

  • 附加到数据对象的过程(Procedure)
  • Procedure的可重用性

Procedure+数据

img{512x368}

Simula继承了Algol,并在其中添加了对象,类,继承和子类。 Simula被认为是第一种面向对象的编程语言,并且在Smalltalk和所有随后的OO语言的开发中具有重要的影响力。

Simula改变了一直以来的从Procedure的角度来看的思维方式,…他将其翻转为…面向对象的视角,即在每种类型的对象中,您都有处理它的所有方法。- Small Talk的实现者Dan Ingalls

1980

接下来是Smalltalk,其中一切都是对象,并且仅通过发送消息与对象进行通信。

img{512x368}

我确实发明了“面向对象”这个术语,但这是一个错误的选择,因为它没有强调消息发送这个更重要的思想。 – Alan Kay: 从A到Z的编程语言:Smalltalk-80 – 2010

1989年

Procedure重用

我们将讨论两个出版物:

如果系统的任何部分取决于另一部分的内部结构,那么复杂度会随着系统大小的平方而增加 – Dan Ingalls面向对象编程— 1989年

继承。 我们看到了继承带来的这种指数级复杂性

对于使用半新的OO语言进行编程的任何人,这应该看起来都很熟悉。关系线无处不在。 – SPAGHETTI CODE的诞生

论文《强类型面向对象编程的接口》中所提到的系统提供了Ada和Modula-2之类的语言中的模块接口的优点,同时保留了可表达性,使无类型的面向对象的语言(如Smalltalk)具有灵活性。

Go interfaces

type Point interface {
    X() int
    Y() int
    Move(int,int)
    Point Equal(Point) bool
}

Go团队在实现interface时并不知道到该论文的存在。由于这两种方法的明显相似性,后来与他们share了该论文。

Go采取了非常相似的方法,但是对上面论文中想法进行了改进,因为Go接口是隐式的,这使Go应用程序解耦并提供了极大的灵活性。

当您尝试分解一个复杂的问题时,您想要尝试将其分解为尽可能少的部分,并且希望它们尽可能独立。 – Dan Ingalls 面向对象编程— 1989

Go的interface和method采用尽可能独立的方式。只要添加正确的方法,任何类型都可以满足任何接口。可以在满足该接口的类型之前或之后定义一个接口。事实证明,这种方式是有效的,而且效果很好。

Go的OO

  • method提供任何类型的消息发送机制
  • 接口通过动态调度多态性提供可重用性

Go提供了像Smalltalk定义的那种面向对象编程,只是更加贴近实际,即使它不包含类,对象或继承。

  • Smalltalk: OO是关于消息发送
  • Go的interface允许方法像Smalltalk的消息一样自由使用,但是是在一种有类型的语言中使用

3. Go的设计哲学

img{512x368}

2007年

在一次耗时45分钟的C++构建过程中……

罗勃·派克:把时钟拨回到2007年9月,当时我正在对一个巨大的谷歌C++程序做一些微小但重要的优化工作,你们都与这个庞大的程序做过交互。我得这个编译过程在我们的巨大的分布式编译集群上跑了约45分钟。我收到一条消息:为C++标准委员会服务的几位Google员工将进行一个演讲,他们将告诉我们C++ 11的新功能。

在一个小时的演讲中,我们听到了有关计划中的35个新功能的消息。……这时我问自己一个问题:”C++委员会真的相信C++的不足之处在于它没有足够的功能吗?” 当然……,简化语言而不是为其添加更多功能将是一个更大的成就。Rob Pike和他的办公室同事(Robert Griesemer、Ken Thompson)回到了办公桌前。这真的让他们开始思考…

现代实用的编程语言应该是什么样?到45分钟构建完成时,他们已经有了一个充满想法的白板。

语言设计的进化过程

我们从头开始构建,仅从C中借鉴了一些小东西,例如运算符和大括号,以及一些通用关键字。当然,我们还借鉴了我们所知道的其他语言的想法。- 罗伯·派克(Rob Pike)

少即是(指数级的)多 – 2012年,在谈到Go的灵感时 Rob Pike

Go的众多祖先和对Go有影响的语言:

img{512x368}

我要说的是,没有哪位语言设计师比这三位语言设计师(Rob Pike, Robert Griesemer, Ken Thompson) 具有更广泛或更深的语言设计专业知识。他们对以前发生的事情有很丰富的了解,他们知道该采摘什么。他们还具有事后观察的优势(后发优势)。这是修复他们认为可以做得更好的事情的机会。

进化不是革命

  • 原则1:大多数思想都来自先前的思想

大多数思想根本不是新事物

进化不是革命:新语言应该巩固而不是发明新特性

等待良好的设计

  • 原则2:No是暂时的,Yes是永远的。

在Go的整个历史中,有很多这样的实例。通常的想法是,在设计语言时,不会出现“撤消(undo)”的情况。如果您今天说“No”,那么您明天总是可以说“Yes”,但是如果今天您说“Yes”,那么您将在很长一段时间或永远被它“困”住…。

如有疑问,请将其排除在外。- Joshua Bloch:关于设计的对话– 2002

共识驱动的设计

  • 原则3: 应该使一切都尽可能简单,但不要过于简单。-爱因斯坦

当我们三个人开始时,这纯粹是研究。…我们从一个想法开始,即我们三个人都必须针对该语言的每个特性进行讨论,因此,无论出于何种原因,都不会在该语言中放入多余的垃圾。 – 肯·汤普森(Ken Thompson)访谈– 2011年,肯从Bell Labs学习了这种做法

有两种构建软件设计的方法。一种方法是使其变得如此简单,以至于显然没有缺陷。另一种方法是使其变得如此复杂,以至于没有明显的缺陷。 – 托尼·霍尔(Tony Hoare)皇帝的旧衣服-1981年,Go采取了第一种方法,而大多数其他语言都采用第二种方法。

快速迭代期待并实现大规模改变

  • 最后一个原则是快速迭代的原则。

当您处于语言的设计阶段时,您将需要进行频繁且有时是巨大的更改。朝着这个期望前进,并围绕它建立您的流程。

4. 今天的Go

img{512x368}

我们来看Go如今是如何演变的。

2019年

Go今天是如何继续进行演化的。

上面的4条原则在该语言的初期,在发行稳定版之前和被采用之前都非常有效。

但我们现在的处境非常不同。我们不再能够将所有贡献者都放在白板上,甚至不能放在如此大的房间中(译注:Go目前的contributor数量庞大)。

现在,我想与大家分享Go项目今天如何进行更改的。

我们的原则是“等待良好的设计”,这似乎意味着这是一种消极的活动,但这与事实相去甚远。真正的意思是,除非我们非常有信心采用正确的方法,否则我们不会接受更改。

这意味着所有问题的默认答案是“否”。“是”的成本非常高,因此需要一个压倒性的理由。

对一件事说“Yes”意味着对其他一切都说“No”。

软件复杂性的主要原因是供应商不加批判地采用了用户想要的几乎所有功能。人们似乎将复杂误解为先进。

不可理解的应该引起怀疑而不是钦佩。- Niklaus Wirth, 1995年

我们对Go进行了长期展望。为下一个十年或两个或更多个而设计。大多数项目的运行时间要短得多,因此通常会接受第一个可通过的解决方案。

随着时间的流逝,经过长时间这种训练的人们已经意识到:如果一个好主意会被接受,或者反之,不好的主意会被拒绝。

由于我们的长期观点,在为Go项目做出贡献时人们挣扎并不罕见。当他们的想法不能被接受时,许多人感到被亲自拒绝。

或更糟糕的是,人们会感到自己不合格或不称职。我记得有这种感觉。

几年前,我创建了一个网站引擎Hugo,随着时间的推移,它成为Go模板的第一用户,并在此过程中发现了几个问题。尽管如此,我感到非常没有资格报告这些问题,因为我认为创建这些库的“专家”显然比我了解更多,并且我无能为力。在第一次或第二次Gophercon上,我碰巧在午餐台上站在Russ Cox旁边,我们开始交谈。他强烈鼓励我报告这些问题,并让我知道他们多么地需要反馈。

几年后,我加入了Go团队,并从这个经验中学到了很多。我观察到的一件事是,Go团队那些加入较久的核心成员有一件事比大多数其他成员都做得更好,这可能不是您的想法。Go团队的老成员已经非常习惯于听到“不”的声音。我们团队成员的提议被拒绝的比率很高,甚至高于Go团队之外的提议。我们已经了解到,每个“No”都与拥有正确的“Yes”仅一步之遥。

因为我们经常听到“No”的声音,所以我们同情别人被拒绝的感觉。

今天我要传达给您的信息是您受到重视和需要。请继续尝试。在接下来的十年或二十年或更长的时间内,您是Go演化的关键部分。

Go开发流程

Go开发流程

实验流程简化始于今年早些时候,Russ Cox谈论了我们用来对Go进行更改的流程以及它的演变方式。在演讲中,他讨论了实验的两个步骤,并简化了我们的迭代过程。

我们的过程不是为了速度而建立的,而是为了正确。我们花费大量时间进行实验和简化,然后完善自己的想法,直到它们正确为止。

你们都是Go伟大实验的一部分,并且是继续构建Go的过程的关键部分

我想与大家分享3种方法,每个人都可以为Go做出贡献。

  • 使用Go -> 识别问题 -> 您遇到的事情/体验并写下来。
  • 您有想法-> 编写建议 -> 纳入反馈
  • 您阅读提案 -> 阅读评论 > 添加您的声音

img{512x368}

Go开发过程:实验 -> 简化 -> 最终交付。通过此提炼过程,想法将准备就绪,我们将进行交付。我想对过程的这一部分及其工作原理提供更多见解。

共识驱动的设计

  • 误解:谷歌有一小群“决策者”
  • 真相:评论者之间达成共识

关于提案过程的事实

  • 事实上,大多提案提案都很小
  • 几乎所有提案的讨论最终都在参与者(评论员)之间达成了共识。
  • 提案审核委员会主要进行一些“园艺劳动”(译者:社区行为培养)

您看到这不是一件非常迷人的工作。我们评论的大多数问题都要求您澄清问题或什么也不做,让对话继续进行。我们还会考虑谁在对话中丢失,并邀请他们加入对话。

当讨论似乎已经解决(赞成或反对)时,我们将关闭其中的一小部分。

让我们看一下最近的一个建议。这只是从最近提案池中随机选取的一个。

它具有一些有趣的属性:大量参与,来自9个参与者的25条评论引用用户问题(体验)。早期该issue尚无共识(由点赞决定)。

在对该想法进行讨论和完善之后,很明显已经达成了普遍共识。

它被标记为“可能接受”,并且留下足够的时间窗口允许任何人提供我们不接受的理由。

这是一组最近审核的提案。您会注意到,他们每个人都引用了之前的评论,并根据这些评论提出了建议。

在提案审核委员会中,通常会有一个人留下评论,但代表所有出席者。Russ Cox通常志愿承担了这个角色,这就是为什么所有这些issue上面都加上他的名字的原因。在大多数情况下,此窗口不会附加注释。我们觉得这个窗口虽然很少使用,但对于建立共识的过程至关重要。

变化是缓慢发生的

这是设计使然。这是缓慢的、谨慎和有条不紊的,以确保我们最终达到想要的目标。

过去十年的主要里程碑

尽管Go的变化缓慢,但增长迅速。我想了解一下过去十年中的一些主要里程碑。

img{512x368}

  • 2009年, Go语言开源,Gopher诞生,Go脱离了Google的实验场;
  • 2010年,获得年度TIOBE语言,Bossie奖,引入append和go tour;
  • 2011年,gccgo合并到GCC中,引入gofix,YouTube在生产中采用了Go;
  • 2012年,Go 1.0发布!发布Go1兼容性承诺;在Google内部发布第一项Go生产服务

img{512x368}

  • 2013年,Packer,Docker,Hugo用Go编写;6个月发布周期;第一个Go大会举行(日本东京)
  • 2014年,Kubernetes使用Go开发;代码仓库由Mercurial→Git;第一次美国和欧洲会议;Go项目贡献者达到500名;
  • 2015年,Go编译器使用Go重写,实现自举;GC精化; Women Who Go&GoBridge born; 印度、中国第一次go大会举行;
  • 2016年,支持HTTP/2和Context;第一次拉丁&中东Go大会举行;最受喜欢的5门编程语言;第一次Go用户调查;贡献者达1000名;

img{512x368}

  • 2017年,GC小于ms级的暂停; 引入type alias;开发人员想要使用编程语言第一名第一次); 13次会议; 第一届贡献者峰会
  • 2018年,引入Go模块;来自Go团队之外的贡献者人数首次超过Go团队;19次Go会议;Go新品牌和logo发布;PR数在github排名第四; 开发人员打算学习的语言中排名第一

5. Go的遗产

img{512x368}

没有时间机器可以达到未来。未来的到来缓慢而又出乎意料。我们不知道Go或世界将会发生什么。但是我们确实知道我们想留下什么标记。

  • 我们希望Go能够留下创新的遗产

Go向主流受众带来了创新的想法,例如goroutine,channel,简单的interface。这些想法现在正在其他语言中出现,我们为这一趋势继续感到高兴。

Go fmt于2009年推出时颇有争议。现在,大多数语言都采用了类似的方法。

也许我们最有影响力的遗产将是,我们像Go一样激励人们挑战既定的规范,并在各处寻找灵感。

  • 我们希望Go留下增强信心和能力的遗产

Go使开发人员能够编写生产服务器软件而无需C和C++所需的额外专业知识,而无需现代Java的复杂性,也无需解释语言的性能成本。

Go比其他任何语言都更能使人们把他们的想法变成现实。当我第一次开始撰写Hugo时,我个人感觉到了这一点,这是Go最吸引我的地方。

其他那些也被赋予了类似的能力和信心的人,其中许多人在本次会议上谈到了Go的创造性用途,包括Florin的家庭自动化研讨会,Ron的机器人,Elias的GUI等。

  • Go改变生活。

我有幸环游世界,在任何地方遇到的男人和女人,他们通常没有CS背景或学位,但能够学习Go并用它来创办公司,获得更好的工作并改善他们和他们家人的生活。

遗产不会为人们留下任何东西。它在人们身上留下了一些东西。- 彼得·斯特普尔

我们每个人都受到过往历史的影响。我们是遗产。我们被影响,我们影响别人。


我的网课“Kubernetes实战:高可用集群搭建、配置、运维与应用”在慕课网上线了,感谢小伙伴们学习支持!

我爱发短信:企业级短信平台定制开发专家 https://tonybai.com/
smspush : 可部署在企业内部的定制化短信平台,三网覆盖,不惧大并发接入,可定制扩展; 短信内容你来定,不再受约束, 接口丰富,支持长短信,签名可选。

著名云主机服务厂商DigitalOcean发布最新的主机计划,入门级Droplet配置升级为:1 core CPU、1G内存、25G高速SSD,价格5$/月。有使用DigitalOcean需求的朋友,可以打开这个链接地址:https://m.do.co/c/bff6eed92687 开启你的DO主机之路。

Gopher Daily(Gopher每日新闻)归档仓库 – https://github.com/bigwhite/gopherdaily

我的联系方式:

微博:https://weibo.com/bigwhite20xx
微信公众号:iamtonybai
博客:tonybai.com
github: https://github.com/bigwhite

微信赞赏:
img{512x368}

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。

Go正走在成为下一个企业级编程语言的轨道上

发展演化了十年的Go语言已经被证明了是云计算时代的首选编程语言,但Go的用武之地显然不局限于此。Kevin Goslar近期在Hacker Noon发表了一篇名为:《Go is on a Trajectory to Become the Next Enterprise Programming Language》的文章,阐述了Go可能成为下一个企业编程语言的理由,这里是那篇文章的中文译文,分享给大家。

img{512x368}

摘要

Go是一种专门为大规模软件开发而设计的编程语言。它提供了强大的开发体验并避免了现有编程语言存在的许多问题。这些因素使其成为最有可能在未来替代Java主导企业软件平台的候选者之一。对于那些寻求在未来几十年内构建大规模云基础架构的安全和前瞻性技术的公司和开源计划而言,我建议它们将Go视为其主要的编程语言。Go的优势如下:

  • 基于现实世界的经验
  • 专注于大型工程
  • 专注于可维护性
  • 保持简单明了
  • 使事情显式且明显
  • 很容易学习
  • 仅提供了一种做事方式
  • 支持简单地内置并发
  • 提供面向计算的语言原语
  • 使用OO – 好的部分
  • 拥有现代化的标准库
  • 强制执行标准化格式
  • 有一个非常快的编译器
  • 使交叉编译变得容易
  • 执行得非常快
  • 需要较小的内存占用
  • 部署规模小
  • 部署完全独立
  • 支持vendor依赖
  • 提供兼容性保证
  • 鼓励提供良好的文档
  • 商业支持的开源

请继续阅读有关上述每个优势点的更多详细信息。然而,在进入Go之前,你应该注意:

  • 不成熟的库
  • 即将到来的改变
  • 没有“硬实时”支持

简介

Go是Google开发的一种编程语言,在过去几年中取得了很大的成功。大部分现代云计算,网络和DevOps平台都是Go语言编写的,例如:DockerKubernetesTerraformETCDistio等。许多公司也将它用于通用软件开发。Go所具备的功能让这些项目吸引了大量用户,而Go的易用性也使得这些项目有了很多的贡献者。

Go的优势来自于简单和经过验证的想法的结合,同时避免了其他语言中出现的许多问题。这篇博客文章概述了Go背后的一些设计原则和工程智慧,并展示它们是如何结合在一起的 – 它们使Go成为下一代大型软件开发平台的优秀候选者。许多编程语言在个别领域都比较强大,但是在将所有领域都结合起来时,没有其他语言能够如此一致地“得分”,特别是在大型软件工程方面。

基于现实世界的经验

Go是由经验丰富的软件行业资深人士创建的,他们长期以来一直感受到现有语言的缺点带来的痛苦。几十年前,Rob PikeKen Thompson在Unix,C和Unicode的发明中发挥了重要作用。在实现了用于JavaScript和Java的V8和HotSpot虚拟机之后,Robert Griesemer在编译器和垃圾收集方面拥有着数十年的经验。在太多次的不得不等待他们的谷歌规模的C++/Java代码库的编译过程的推动下,他们开始着手创建一门新的编程语言,这门语言中凝聚了他们通过编写半个世纪代码过程中所学到的一切。

专注于大型工程

几乎任何编程语言都可以成功构建小型工程项目。当成千上万的开发人员在数十年的持续时间压力下在包含数千万行代码的大量代码库上进行协作时,真正痛苦的问题就会发生。这会导致以下问题:

  • 超长的编译时长会中断开发过程
  • 代码库由几个人/团队/部门/公司拥有,混合了不同的编程风格
  • 该公司雇佣了数千名工程师,架构师,测试人员,Ops专家,审计员,实习生等,他们需要了解代码库,但需要具有广泛的编码经验
  • 依赖于许多外部库或运行时,其中一些不再以其最初的形式存在
  • 每行代码在代码库的生命周期内平均被重写了10次,留下了疤痕,瑕疵和技术偏移
  • 文档不完整

Go专注于减轻这些大规模的工程难题,有时是以使小型工程变得更加繁琐为代价,例如在这里和那里需要一些额外的代码。

专注于可维护性

Go强调尽可能多地将工作转交到自动代码维护工具中。Go工具链提供了最常用的功能,如格式化代码和自动package导入、查找符号的定义和用法、简单的重构以及代码味道的识别。由于标准化的代码格式化和单一的惯用方式,机器生成的代码更改看起来非常接近Go中人为生成的更改。并而使用类似的模式,使得人和机器的协作更加无缝。

保持简单直接

初级程序员为简单问题创建简单的解决方案。高级程序员为复杂问题创建复杂的解决方案。伟大的程序员找到复杂问题的简单解决方案。-  查尔斯康奈尔

很多人都对Go不包含他们喜欢的其他语言概念感到惊讶。Go确实是一种非常小而简单的语言,只包含最少的正交和经过验证的概念。这鼓励开发人员以最少的认知开销编写最简单的代码,以便许多其他人可以理解并使用它。

使事情显式而明显

良好的代码是显而易见的,避免聪明,模糊的语言功能,扭曲的控制流和间接性。

许多语言都致力于使编写代码变得高效。然而,在其生命周期中,人们将花费大约(100倍)的时间阅读代码,而不是首先编写所需的代码。例如,审查,理解,调试,更改,重构或重用它。在查看代码时,通常只能看到并理解它的一小部分,通常没有对整个代码库的完整理解。为了解释这一点,Go将一切都显式化了。

一个例子是错误处理。让异常在各个点中断代码并使沿着调用链处理可能会更容易。Go需要手动处理或返回每个错误。这使得它可以准确地显示代码可以被中断的位置以及如何处理或包装错误。总的来说,这使得错误处理更容易编写,但更容易理解。

简单易学

Go非常小而且简单,可以在短短几天内研究整个语言及其基本概念。根据我们的经验,经过不超过一周的培训(与其他语言的以月为单位相比),初学者可以理解Go专家编写的代码,并为此做出贡献。为了方便大量人群,Go网站提供了所需的所有教程和深入的文章。这些教程在浏览器中运行,允许人们在将Go安装到本地计算机上之前学习和使用Go。

一种做事方式

Go语言通过个人自我表达赋予团队合作能力。

在Go(和Python)中,所有语言特征都是正交的并且彼此互补,通常做某事只有一种方法。如果您要求10位Python或Go程序员解决问题,您将获得10个相对类似的解决方案。不同的程序员在彼此的代码库中感觉更有家的感觉。在查看其他人的代码时,每分钟的WTF更少,而且人们的工作更好地融合在一起,从而形成一个人人都为之骄傲并且喜欢工作的一致性。这避免了大规模的工程问题,例如:

  • 开发人员将良好的工作代码视为“混乱”,并要求在他们可以使用之前重写它,因为他们不会像原作者那样思考。
  • 不同的团队成员在该语言的不同子集中编写相同代码库的部分内容。

img{512x368}
来源:https://www.osnews.com/story/19266/wtfsm

简单,内置并发

Go专为现代多核硬件而设计。

目前使用的大多数编程语言(Java,JavaScript,Python,Ruby,C,C ++)都是在20世纪80年代到2000年代设计的,当时大多数CPU只有一个计算核心。这就是为什么它们本质上是单线程的,并将并行化视为事后增加的边缘情况,通过诸如线程和同步点之类的附加组件实现,这些附加组件既麻烦又难以正确使用。第三方库提供了更简单的并发形式,如Actor模型,但总有多个选项可用,导致语言生态系统碎片化。今天的硬件拥有越来越多的计算内核,软件必须并行化才能在其上高效运行。Go是在多核CPU时代编写的,并且在语言中内置了简单,高级的CSP风格的并发特性。

面向计算的语言原语

在基础层面上,计算机系统接收数据,处理它(通常经过几个步骤),并输出结果数据。例如,Web服务器从客户端接收HTTP请求,并将其转换为一系列数据库或后端调用。一旦这些调用返回,它就会将接收到的数据转换为HTML或JSON并将其输出给调用者。Go的内置语言原语直接支持这种范例:

  • 结构体代表数据
  • reader和writer代表流式IO
  • 函数处理数据
  • goroutines提供(几乎无限制的)并发
  • 通道用于管理并发处理步骤之间的数据

由于所有计算原语都是由语言以直接的形式提供的,因此Go源代码可以更直接地表达服务器执行的操作。

OO – 好的部分

img{512x368}
在基类中改变某些东西的副作用

面向对象非常有用。这几十年OO的应用是富有成效的,并且让我们了解它的哪些部分比其他部分可以更好地扩展。基于这些认知,Go采用面向对象的新方法。它保留了封装和消息传递等优点。Go避免了继承,因为它现在被认为是有害的,Go为组合提供头等的支持

现代标准库

许多当前使用的编程语言(Java,JavaScript,Python,Ruby)是在互联网成为当今无处不在的计算平台之前设计的。因此,这些语言的标准库仅为未针对现代互联网优化的网络提供相对通用的支持。Go是十年前创建的,当时互联网已经全面展开。Go的标准库允许在没有第三方库的情况下创建更复杂的网络服务。这可以防止使用第三方库的常见问题:

  • 碎片化:实现相同功能的总有多种选择
  • 膨胀:库通常实现的不仅仅是它们的用途
  • 依赖地狱:库通常依赖于特定版本的其他库
  • 质量未知:第三方代码可能具有可疑的质量和安全性
  • 未知支持:第三方库的开发可以随时停止
  • 意外更改:第三方库通常不像标准库那样进行严格的版本管理

Russ Cox的更多背景信息。

标准化格式

Gofmt的风格是没有人喜欢的,但gofmt是每个人的最爱。 – Rob Pike

Gofmt是一种以标准化方式格式化Go代码的程序。它不是最漂亮的格式化方式,而是最简单,最不讨厌的方式。标准化的源代码格式化具有惊人的积极影响:

  • 重点讨论重要主题:它消除了围绕标签与空格,缩进深度,每行长度,空行,花括号放置等的一系列无意义的争论
  • 开发人员在彼此的代码库中感到宾至如归,因为其他代码看起来很像他们编写的代码。每个人都喜欢自由地按照自己喜欢的方式格式化代码,但如果其他人冒昧地按照他们自己喜欢的方式格式化>代码,那么每个人都讨厌它。
  • 自动代码更改不会弄乱手写代码的格式,例如通过引入意外的空白更改。

许多其他语言社区现在正在开发gofmt等价物。当构建为第三方解决方案时,通常会有几种竞争格式标准。例如,JavaScript世界提供PrettierStandardJS。可以一起使用其中之一或两者。许多JS项目都没有采用它们,因为这是一个额外的决定。Go的格式化程序内置于该语言的标准工具链中,因此只有一个标准,每个人都在使用它。

快速编译

img{512x368}
来源:https://xkcd.com/303

大型代码库的长编译时间是引发Go语言起源的一个微小的原因。Google主要使用C++和Java,与Haskell,Scala或Rust等更复杂的语言相比,它可以相对快速地编译。尽管如此,当编译大型代码库时,即使是少量的慢速也会把人激怒,编译工作流中断导致编译延迟。Go是从头开始设计的,以使编译更有效,因此编译器速度非常快,几乎没有编译延迟。这为Go开发人员提供了类似于脚本语言的即时反馈,并具有静态类型检查的额外好处。

交叉编译

由于语言运行时非常简单,因此它已被移植到许多平台,如macOS,Linux,Windows,BSD,ARM等。Go可以开箱即用于编译所有这些平台的二进制文件。这使得我们可以轻松地从一台机器来进行部署。

快速执行

Go有着接近C的速度。与JITed(即时编译)语言(Java,JavaScript,Python等)不同,Go二进制文件不需要启动或预热时间,因为它们作为已编译和完全优化的本机代码提供。Go垃圾收集器仅以微秒的指令引入可忽略的暂停。在其快速的单核性能上面,Go使得利用所有的CPU内核更容易

小内存占用

像JVM,Python或Node这样的运行时不仅仅在运行时加载程序代码。它们还会加载大型且高度复杂的基础架构,以便在每次运行时编译和优化程序。这使得它们的启动时间变慢并导致它们使用大量(数百MB)的RAM。Go进程的开销较小,因为它们已经完全编译和优化,只需要运行。Go还以非常节省内存的方式存储数据。这在内存有限且昂贵的云环境中以及在开发期间非常重要,在开发期间我们希望在单个机器上快速启动整个堆栈,同时为其他软件留下内存。

小部署规模

Go二进制文件的大小非常简洁。Go应用程序的Docker镜像通常比用Java或Node编写的等效文件小10倍,因为它不需要包含编译器,JIT,并且需要更少的运行时基础结构。这在部署大型应用程序时很重要。想象一下,将一个简单的应用程序部署到100个生产服务器上 使用Node / JVM时,我们的docker仓库必须提供100个docker镜像@ 200 MB = 20 GB(总共)。这需要镜像仓库耗费一些时间来服务。想象一下,我们希望每天部署100次。使用Go服务时,Docker镜像仓库只需提供100个Docker镜像@ 20 MB = 2 GB。可以更快,更频繁地部署大型Go应用程序,从而允许重要更新更快地实现生产。

自包含部署

Go应用程序部署为包含所有依赖项的单个可执行文件。不需要安装特定版本的JVM,Node或Python运行时。不必将库下载到生产服务器上。不需要对运行Go二进制文件的机器进行任何更改。甚至不需要将Go二进制文件包装到Docker中来共享它们。您只需将Go二进制文件拖放到服务器上,无论该服务器上运行的是什么,它都会在那里运行。上述描述的唯一例外是使用net和os/user包时的动态链接glibc库时。

vendor依赖关系

Go故意避免使用第三方库的中央存储库。Go应用程序直接链接到相应的Git存储库,并将所有相关代码下载(vendor保存)到他们自己的代码库中。这有很多好处:

  • 我们可以在使用之前查看,分析和测试第三方代码。此代码与我们自己的代码一样,是我们应用程序的一部分,应符合相同的质量,安全性和可靠性标准。
  • 无需永久访问存储依赖项的各个位置。可以一次性的从任何地方(包括私人Git仓库)获取您的第三方库,并永久拥有它们。
  • 在checkout后编译代码库不需要进一步下载依赖项。
  • 如果互联网上某处的代码存储库突然提供不同的代码,也不会造成surprises。
  • 即使软件包存储库服务性能变慢或托管软件包不再存在,部署也不会中断。

兼容性保证

Go团队承诺,现有的程序将继续适用于新版本语言。这使得即使是大型项目也可以轻松升级到更新编译器的版本,并从新版本带来的许多性能和安全性改进中受益。同时,由于Go二进制文件包含了他们需要的所有依赖项,因此可以在同一服务器计算机上并行运行使用不同版本的Go编译器编译的二进制文件,而无需进行复杂的设置多个版本的运行时或虚拟化。

文档

在大型工程中,文档对于使软件易于访问和维护非常重要。与其他功能类似,Go中的文档简单实用:

  • 它嵌入在源代码中,因此两者可以同时维护。
  • 它不需要特殊的语法 – 文档只是普通的源代码注释。
  • 可运行的单元测试通常是最好的文档形式,所以Go允许你将它们嵌入到文档中
  • 所有文档实用程序都内置在工具链中,因此每个人都使用它们。
  • Go linter需要导出元素的文档,以防止“文档债务”的积累。

商业支持的开源

当商业实体在公开场合发展时,一些最流行和最全面设计的软件就会发生。这种设置结合了商业软件开发的优势 – 一致性和优化,使系统健壮,可靠,高效 – 具有开放式开发的优势,如来自许多行业的广泛支持,来自多个大型实体和许多用户的支持,以及长期支持,即使商业支持停止。Go就是这样开发的。

缺点

当然,Go并不完美,每种技术选择总是有利有弊。在进入Go之前,这里有一小部分需要考虑的方面。

未成熟

虽然Go的标准库在支持HTTP/2服务器推送等许多新概念方面处于行业领先地位,但与JVM生态系统中存在的相比,用于外部API的第三方Go库可能还不那么成熟。

即将到来的变化

Go团队知道几乎不可能改变现有的语言元素,因此只有在完全开发后才会添加新功能。在经历了10年稳定的故意阶段后,Go团队正在考虑对语言进行一系列更大的改进,作为Go 2.0之旅的一部分。

没有硬实时

虽然Go的垃圾收集器只引入了非常短的中断,但支持硬实时需要没有垃圾收集的技术,例如Rust。

结论

这篇博客文章给出了一些明智的背景知识,但往往没有那么明显的选择进入Go的设计,以及当他们的代码库和团队成数量级增长时,他们将如何从许多痛苦中拯救大型工程项目。总的来说,他们将Go定位为寻求Java之外的现代编程语言的大型开发项目的绝佳选择。


我的网课“Kubernetes实战:高可用集群搭建、配置、运维与应用”在慕课网上线了,感谢小伙伴们学习支持!

我爱发短信:企业级短信平台定制开发专家 https://tonybai.com/
smspush : 可部署在企业内部的定制化短信平台,三网覆盖,不惧大并发接入,可定制扩展; 短信内容你来定,不再受约束, 接口丰富,支持长短信,签名可选。

著名云主机服务厂商DigitalOcean发布最新的主机计划,入门级Droplet配置升级为:1 core CPU、1G内存、25G高速SSD,价格5$/月。有使用DigitalOcean需求的朋友,可以打开这个链接地址:https://m.do.co/c/bff6eed92687 开启你的DO主机之路。

我的联系方式:

微博:https://weibo.com/bigwhite20xx
微信公众号:iamtonybai
博客:tonybai.com
github: https://github.com/bigwhite

微信赞赏:
img{512x368}

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats