标签 RobPike 下的文章

Go是编程语言世界的“特斯拉”

img{512x368}

Go技术专栏“改善Go语⾔编程质量的50个有效实践”正在慕课网火热热销中!本专栏主要满足广大gopher关于Go语言进阶的需求,围绕如何写出地道且高质量Go代码给出50条有效实践建议,上线后收到一致好评!78元简直就是白菜价,简直就是白piao! 欢迎大家订阅!

img{512x368}

本文翻译自《GO — The TESLA Of Programming World》 – https://medium.com/globant/go-the-tesla-of-programming-world-a3ad8584723e。内容有改编

免责声明:本文的内容仅用于娱乐和提供信息。我强烈建议读者不要基于这篇文章来进行专业领域的决策。这里表达的观点仅是作者本人的观点,绝不代表作者所属任何组织的观点,思想或意识形态。

缘起

img{512x368}

回味着晨起后的五谷豆浆在口中的余香,反思着二闺女四个月来的成长情况,一篇关于Go终于拥抱泛型的文章映入眼帘,紧接着就是3000多辆中国制造的出口欧洲的特斯拉Model 3汽车抵达比利时泽布吕赫港的消息。一个奇怪的想法油然而生并钻入了我的大脑:如果说Go和Tesla是通过“如何不陷入困境并对未来进行超前思考”而收到回报的新典范,那么保留了父母物种复杂的身体解剖结构的新生婴儿如何成长和发展自己的性格和态度呢。这就是让我感觉到Go确实是编程语言中的TESLA的原因和驱动力。

TESLA在汽车世界和Go在编程世界中的崛起和成长有着惊人的相似:

  • 两者的诞生都打破了他们各自领域中已约定俗成的做事方式的束缚,并提出了一种新的高效方法来完成相同的事情;
  • 两者都取得了惊人的成绩,并按照各自的增长计划前进,并似乎正在赢得这场战斗;
  • 两者已完成的和目标都是保留各自领域的优秀部分,并在硬性方面有所改进;
  • 两者都将成为各自领域帝国的未来。

开端

与普遍的看法相反,是通用汽车而不是特斯拉生产了世界上第一批量产的电动汽车,名为EV1。这辆车仅租赁而不出售,在生产了几年后,通用汽车召回了所有EV1汽车并销毁了它们!这促使马丁·埃伯哈德( Martin Eberhard)和马克·塔彭宁( Marc Tarpenning)启动TESLA(最初是TESLA汽车公司)来挑战大型汽车制造商,并引领世界进入零排放的出行方式。

在使用Go之前,Google的开发人员面临着编译时间,代码可维护性等问题,这些问题直接影响了生产力。另外,他们需要一种具有更好的并发支持的编程语言,以更好地利用多核处理器的特性。同时更易于学习,易于实现,编写更少的程序代码。Google当时主要使用C++,并且对代码中的任何问题或较小的修改都将花费一天多的时间。C++的另一个缺点与它的内存管理模型有关:内存的分配和释放不是动态的,并且如果程序员没处理好内存分配与释放事宜,就会导致内存泄露,导致应用程序运行变慢并最终崩溃。

在Go之前的时代,在项目开始时,需要选择要使用的编程语言:使用Python可简化操作,但也放弃了内存,CPU管理和可移植性;使用Java可利用其垃圾回收、自动内存管理和可移植性,但却以放弃简单为代价;选择其他诸如C++之类的语言则具有复杂的内存管理模型,并且没有内置的垃圾回收器。走进Go:一种简单易学的编程语言,由Rob Pike等设计的一种带有内置垃圾收集器(比Java中的垃圾收集器简单得多)的语言,支持静态编译并支持并发编程。

经过上面仔细剖析,可以注意到TESLA和Go的成立都是由于出现了机会。一个触发了他们各自的创造者开发出一种方法,试图解决各自领域中“当时”缺点的机会。

自持(自举)

电动汽车最重要的组件是电池,而对于编程语言来说,其最重要的组件则是被称为编译器的软件。TESLA的埃隆·马斯克(Elon Musk)最近宣布,他们将开发一种“tabless”电池,这将有助于为其车辆提供更好的续驶里程。重要消息,TESLA将自行生产这些电池。

为什么特斯拉一开始就没有自己的电池制造部门?没有具体的原因,但特斯拉优先考虑在汽车制造方面获得他们需要的专业知识,然后冒险为他们的汽车制定内部电池生产计划。

Go编译器是“语言实现自身”的一个典型案例。在Go 1.4版本之前,Go语言的编译器是用C编写的,后来被用Go编写的代码取代了

这样的自举变化提供了诸多好处,比如:可以更好地控制编译器,因为Go更简单,这使得调试编译器问题更快更容易。此外,Go还对单元测试和性能分析提供了出色的内置支持。

进一步阅读:对于你们当中好奇心重的人,在下面的资源链接中提供了一些资料,这些资料解释了对Go编译器进行更改的动机。https://docs.google.com/document/d/1P3BLR31VA8cvLJLfMibSuTdwTuF7WWLux71CYD0eeD8/edit

创新

在当今竞争激烈的世界中,创新一直是成功的关键所需。TESLA和Go都采用了颠覆性创新的方法。具有破坏性并不意味着新进入者必须挑战/修改/改变已经建立的完成任务方式的方方面面,而是在当前趋势下采取一种不同,更好,更简单,通常更有效的方式来完成任务。

根据维基百科,颠覆性创新是指一种创建新的市场和价值网络并最终破坏现有的市场和价值网络,取代当前已建立的市场的领先的公司,产品和联盟的创新。

TESLA通过几乎不存在的电动汽车制造提案进入了以燃油动力汽车为主的汽车制造市场。TESLA保留了久经考验的车辆空气动力学设计,但彻底改变了这些车辆自我推进的方式。自从他们的第一款汽车问世以来,大约12年之久,TESLA便将这场斗争推向了传统汽车制造商的家门口,而这些传统汽车制造商的生存受到了威胁,除非他们也通过创新。TESLA引领着交通的未来:零排放,可再生能源驱动的车辆。

Go是建立在现有编程语言,例如C,Pascal和Oberon的久经考验的优势之上的编程语言。摆在Go面前的最大、最复杂的难题就是:如何实现简单和最小化。C语言已经很简单,但是Go将简单性提高到了更高的水平。Go以其在学习和实现方面的简单性以及遵循一种简单的方法来实现复杂的编程概念(如并发性)而广受赞赏。最初,Go旨在解决Google的内部编程障碍。尽管技术进步意味着多核处理器从2006年开始成为标准,但没有一种编程语言可以充分利用这种处理能力,从而导致更快,更好的代码执行时间以及对运行代码的基础硬件和软件基础设施的有效利用。

颠覆性创新方法从Go如何处理某些编程范例得以反映出来。Go允许使用OOP样式的语法,但实际上它并不是面向对象的语言!与其他OO语言一样,它具有类型和方法,但是缺少类型层次结构。Go对继承概念的理解与JAVA等其他OO语言所追求的完全不同。与Java中需要两个关联类进行显式声明不同,Go根据某些合理的条件隐式计算类型关联关系。

尽管进入了已经很拥挤的编程语言世界,Go在短短的十二年间就引起了巨大轰动,可以说是最受喜爱,使用最多和增长最快的编程语言之一。根据当前的市场报告,Go威胁着编程语言中的巨擘Java,并且被广泛视为未来的(头部)编程语言。

成长

TESLA成立于2003年,当时不为人知。2008年,其首款产品发布,到2020年截至7月,TESLA已超越丰田,成为全球最具价值的汽车制造商。这就是创新的TESLA造成的破坏,它很可能取代APPLE成为全球市值最高的公司(按市值计算)。TESLA被公认为领先于其他汽车制造商至少十年的公司!

跨平台Go语言与Google自己的DART一起,是Github上增长最快的编程语言之一。截至2020年第三季度,它是GitHub上第四大最受欢迎的语言

根据2020年StackOverflow开发人员调查,它是StackOverflow上最受欢迎的语言第5名。Go的发展绝非偶然,也不是炒作,尤其是当您考虑到Docker,Kubernetes,Terraform之类的应用程序完全是用Go编写的。Go也是在职专业人员希望在2020年学习的编程语言之首。借助Go 2.0,Go有望成为企业软件开发的首选语言,以取代长期以来的王者JAVA。

img{512x368}

观念模式

大多数TESLA的用户都是从汽油动力汽车迁移而来,为了熟悉自己的新汽车,用户需要进行重大的观念转变。用户需要了解,他们需要跟踪的不是油位和冷却液位,而是电池电量。用户还需要了解充电周期以及不正确的充电技术对车辆的影响。

对于Go,此处的用户既是开发人员,又是推进Go项目实施工作的用户。开发人员需要特别了解项目需求,优势以及与Go相关的局限性。开发人员经常会从Go入手,这是对这门当前时代编程语言的一种狂热,从而常常忽略了它的局限性。诸如泛型和类型层次结构之类的简单概念也可以成为使用或不使用Go进行项目开发的成败之举。

支持

对于TESLA,售后支持的挑战来自于(充电)基础设施,特别是对基础设施的收费。这可能不是其母国(即美国)的最大障碍,但如果TESLA要扩展到中国等国家,则需要与当地政府机构合作开发必要的基础设施,以维持电动汽车的机动性。

关于Go,最大的障碍是拥有一个支持用户的技术社区。在这一领域,JAVA胜过其他已创立的语言,变得非常有说服力。JAVA得到了来自最大社区的支持。像Go这样发展壮大的语言肯定需要建立强大的,熟练的技术社区,这不仅将有助于Go成长为一种语言,而且还有助于其改进。

可持续性

TESLA建立了自己的品牌之后,要在销售和服务过程中提供最佳的客户支持来维持它,这是一项具有挑战性的工作。此外,由于其雄心勃勃的计划是通过提供新产品来迎合大众,因此需要观察他们在生产过程中是否能够维持同样高水平的质量控制。

与此处的TESLA相比,Go具有更大的可持续性关注。即使基于最小化和简单的原则构建,Go v2.0仍有望引入泛型。展望未来,它的创造者需要确保永不包含任何功能,概念和改进,不要偏离他们的愿景,并且最终不要成为像JAVA那样概念繁多的语言。早期采用JAVA的人也可能会告诉它,它起初只是很小的,但随着时间的流逝,它变得很沉重。Go应该避免走那条路

总结

考虑到上面所有观点,现在应该很清楚:TESLA取得成功的创新但艰难的道路同样适用于Go。它们各自领域中的困难本质上可能有所不同,但会以相似的原则影响着它们。


“Gopher部落”知识星球开球了!高品质首发Go技术文章,“三天”首发阅读权,每年两期Go语言发展现状分析,每天提前1小时阅读到新鲜的Gopher日报,网课、技术专栏、图书内容前瞻,六小时内必答保证等满足你关于Go语言生态的所有需求!星球首开,福利自然是少不了的!2020年年底之前,8.8折(很吉利吧^_^)加入星球,下方图片扫起来吧!

我的网课“Kubernetes实战:高可用集群搭建、配置、运维与应用”在慕课网热卖中,欢迎小伙伴们订阅学习!

img{512x368}

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

2020年4月8日,中国三大电信运营商联合发布《5G消息白皮书》,51短信平台也会全新升级到“51商用消息平台”,全面支持5G RCS消息。

著名云主机服务厂商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
  • “Gopher部落”知识星球:https://public.zsxq.com/groups/51284458844544

微信赞赏:
img{512x368}

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

重度使用Go的“后遗症“,你有吗?

img{512x368}

有一种未经证实的说法:Go诞生于C++程序的漫长构建过程中。如果C++编译很快,那么Robert Griesemer、Rob Pike和Ken Thompson这三位大佬也没有闲暇时间一起喝着咖啡并决定是时候设计一门新语言了。的确,Go语言诞生后,其简洁的语法、极速地构建、新颖的并发结构、体验优良的工具链以及完成度不低的标准库吸引了很多C/C++程序员转型成为Gopher并开始重度使用Go,比如鄙人^_^。如果能一直使用Go总也是不错的,但偶尔因项目需要可能还会写一些C/C++代码,这时候很多Gopher发现自己在长期重度使用Go之后出现了一些“后遗症”!这里我们就来细数一下都有哪些“后遗症”,各位Gopher小伙伴们也自我评估一下,这些“后遗症”是否也发生在你的身上^_^。

1. 声明变量时类型与变量名的顺序总写反

Go语言是C家族编程语言的一个分支,和C/C++一样,Go也是静态编译型语言,这就要求在使用任何变量之前需要先声明这个变量,无论使用常规声明方法还是短声明形式

但Go采用的变量声明语法颇似Pascal:变量名在前,变量类型在后,这与C/C++恰好相反:

Go:

var a, b int

var p, q *int

vs.

C/C++:

int a, b;

int *p, *q;

这样,gopher在长期使用Go编写代码后,一旦回归写C/C++代码,遇到的第一个问题就是经常在声明的时候将变量名与类型写反^_^。还好C/C++编译器会发现并告知我们这个问题,并不会给程序带来实质性的伤害。

  • 发病指数:3

  • 危害指数:1

2. 经常在函数中使用“短声明”形式声明变量

短声明不是Go语言独创的语法。短声明的好处正如其名:短小,无需显式提供变量类型,编译器会根据赋值操作符后面的初始化表达式的结果自动为变量赋予适当类型。因此,它成为了Gopher们喜爱和重度使用的语法。但短声明在C/C++中却不是合法的语法元素:

int main() {
    a := 5; //  error: expected expression
    printf("a = %d\n", a);
}

和上面的问题一样,C/C++编译器会发现并告知我们这个问题,并不会给程序带来实质性的伤害。

  • 发病指数:2

  • 危害指数:1

3. 总是忘记代码行结尾的分号

Go的正式标准语法是带有分号的,下面的代码片段才是编译器眼中认为正确的代码形式:

package main;

import "fmt";
import _ "database/sql";

type Foo struct {
    Name string;
    Age int;
};

func main() {
    var a, b = 1, 2;
    println(a, b);
    if a == 1 { fmt.Println("a = 1"); }
}

但这种形式显然与我们日常“惯用”的代码形式有很大不同,我们日常编写Go代码时极少手写分号。Go设计者当初为了简化代码编写,提高代码可读性,选择了由编译器在词法分析阶段自动在适当位置插入分号的技术路线,并在Go语言规范中描述了分号的插入规则:

1. 在Go中,除去注释,如果一个代码行的最后一个token为下列情况时,则编译器会将一个分号自动插入在此字段后:

    - 一个标识符;
    - 一个整数、浮点数、实数虚部、rune(码点)或者字符串字面量;
    - 关键字之一:break、continue、fallthrough和return;
    - 自增运算符++、自减运算符--、右括号)、]或}。

2. 为支持在一个代码行中放置复杂语句,分号可能被插入在右小括号)或者右大括号}之前。

被Go编译器惯坏了的Gopher们一旦回到编写C/C++代码,遗忘代码行尾的分号的“后遗症”行为就见怪不怪了。

  • 发病指数:5

  • 危害指数:2

4. 遇到在其他头文件中定义的头母小写的函数时总以为不能直接使用

在Go中,头母大写的包级变量、常量、类型、函数、方法都是导出的,即对外部包可见。反之,头母小写的则为包私有的,仅在包内使用。一旦习惯了这样的规则,在切换到其他语言中,就会产生“心理后遗症”:遇到在其他头文件中定义的头母小写的函数时总以为不能直接使用。

  • 发病指数:3

  • 危害指数:2

5. 写条件分支语句、选择分支语句和循环语句时,总忘记给条件加上括号

同样是出于简化代码,增加可读性的考虑,Go设计者最初就取消掉了条件分支语句(if)、选择分支语句(switch)和循环语句(for)中条件表达式外围的小括号:

func f() int {
    return 5
}
func main() {
    a := 1
    if a == 1 { // 无需小括号包裹条件表达式
        fmt.Println(a)
    }

    switch b := f(); b { // 无需小括号包裹条件表达式
    case 4:
        fmt.Println("b = 4")
    case 5:
        fmt.Println("b = 5")
    default:
        fmt.Println("b = n/a")
    }

    for i := 1; i < 10; i++ { // 无需小括号包裹循环语句的循环表达式
        a += i
    }
    fmt.Println(a)
}

这恰与C/C++“背道而驰”,于是我们经常看到在编写C/C++的gopher为大量的如下编译器错误而苦恼:

int main()
{
    int a = 1;
    if a == 1 { // error: expected '(' after 'if'
        printf("a = 1\n");
    }

    int i = 0;
    for i = 1; i < 10; i++ { // error: expected '(' after 'for'
        a += i;
    }
}

  • 发病指数:4

  • 危害指数:2

6. 总是忘记在switch case语句中添加break

C/C++的选择分支语句有一个陷阱,那就是case语句中如果没有显式加入break语句,那么代码将向下自动掉落执行。Go在最初设计时填了这个“坑”,重新规定了swtich case语义,默认不自动掉落(fallthrough),除非开发者显式使用fallthrough关键字。

适应了Go的switch case语句的语义后,再回来写C/C++代码就会存在潜在的“风险”:

int main()
{
    int a = 1;
    switch(a) {
        case 1:printf("a = 1\n");
        case 2:printf("a = 2\n");
        case 3:printf("a = 3\n");
        default:printf("a = ?\n");
    }
}

这段代码按go语义编写switch case,编译运行后得到的结果如下:

a = 1
a = 2
a = 3
a = ?

我们看到代码首先匹配到了 case1的情况,然后一路自动掉落到default case。这个“后遗症”存在很大危害,因为这样编写的代码在C/C++编译器眼中是完全合法的,但所代表的语义却完全不是开发人员想要的。这样的程序一旦流入到生产环境,其缺陷可能会引发生产故障。

  • 发病指数:3

  • 危害指数:4

对于这样的问题,一些C/C++ lint工具可以将其检测出来,因此建议写C/C++代码的Gopher在提交代码前使用lint工具对代码做一下检查。

参考资料

  • https://go101.org/article/line-break-rules.html

  • https://tip.golang.org/ref/spec#Semicolons

  • https://medium.com/golangspec/automatic-semicolon-insertion-in-go-1990338f2649


只有写书者,才能体会到写者的艰辛!Go专栏:《改善Go语言编程质量的50个有效实践》也是我努力了一年多才打磨雕琢出来的心血之作。自从上线后,收到大家的热烈关注和好评!现在恰逢双11慕课大促,欢迎有意愿在Go这条技术路线上进阶的朋友们订阅,在学习过程中欢迎随时反馈和交流!

img{512x368}

我的网课“Kubernetes实战:高可用集群搭建、配置、运维与应用”在慕课网热卖中!欢迎小伙伴们学习支持!双十一慕课网优惠空前!别错过机会哦!

img{512x368}
微博:https://weibo.com/bigwhite20xx
微信公众号:iamtonybai
博客:tonybai.com
github: https://github.com/bigwhite

微信赞赏:
img{512x368}

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

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系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