为什么我放弃 Scala 选择Go?
Posted StuQ
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么我放弃 Scala 选择Go?相关的知识,希望对你有一定的参考价值。
战争是由胜者推翻旧帝国,来撰写新历史。在科技比拼里,强大公司都在写编程语言,创建新帝国。
我认为我第一次看到类型系统的积极一面,是在 Scala 上。
就个人而言,经历无数的 php 静默错误和一些奇怪行为后,有了支持类型检查和妥当的测试,代码终于能正常运行。除此之外,它要在重构之后继续之前的工作,否则会破坏类型检查或测试用例。虽然 Java 也能提供这些功能,但并没有 FP 的优雅,却拥有所有的 EE 的麻烦。
Scala 还有一些特质。它允许你创建自己的运算符或覆盖现有运算符,本质上是具有非字母数字标识符的一元和二元函数。你还可以通过宏(供编译器调用的用户定义函数)来扩展编译器,并通过隐式类(也称为“pimp库”模式)来丰富第三方库。
但 Scala 也有它自身的问题。
Martin Odersky 曾提出的一个话题承认并彻底描述了 Scala 编译器的慢,并为此感到沮丧。与庞然大物和复杂的依赖关系树结合,这是一个复杂的解决机制 —— 之后几年里,工程师们就像保姆照顾婴儿那样看护着它 —— 在核心模块中添加一个模型类,这是一次休整,但利弊共存。最重要的是,编码的反馈时间会变得难以接受。(例如:代码测试重构在迭代间延迟)。
缓慢的编译时间和一个庞然大物会导致缓慢 CI,反过来,就导致了冗长的部署。幸运地是,聪明的工程师可以并行在不同的节点上测试,把整体上的 CI 时间从一个小时压低到 20 分钟。结果很成功,但在敏捷部署上还是存在问题。
IDE 支持很差。 Ensime 在多个 Scala 版本项目(在不同模块上的不同版本)上存在的问题使得导入、非 grep 型跳转到定义等的优化无法实施。这意味着所有开源和社区驱动的 IDE(例如 Vim、Emacs、Atom)都会有不太理想的特性集。这种语言似乎太复杂,而不能创建工具集!
Scala 集成也尝试进行多个项目构建,最引人注目的是 Jetbrains 的 Intellij Scala 插件,它支持跳转到定义,允许我们跳转到旧版 JAR 包,而不是已修改的文件中。我们可以使用高级语言特性查看已破坏的高亮显示。
从积极的一面来看,我们只要根据笔记本电脑的散热板的响度,就能准确地判断该程序员使用的是 IDEA 还是 sbt。但对于 MacBook Pro 用户来说,散热非常耗电,不能没有电源插座。
对面向对象的批评由来已久,但真正进入人们视线是在 Lawrence Krubner 发布博文之后。从那以后,选择非面向对象语言的想法开始被接受。
我们中就有好几个成员一度在学习 Haskell。
Coda Hale 发给 Scala team 的邮件“Yammer 放弃 Scala”在 2011 年引起轰动,虽然消息陈旧,但当大家观念发生转变后,就会发现 Coda Hale 说的很有道理。参考以下叙述:
“因为有些内容只有库作者需要理解,部分的复杂度已经被移除了。但是当一个库的 API 牵涉到所有的复杂度时(因为大部分的功能在调用空间中解决细节问题),工程师就需要对库运行的机制和转变成 cargo-culting 代码片段的设计模型有一个精确地认识。”
从那时起,大玩家也纷纷加入,比如 Twitter 和 LinkedIn。
以下是 Raffi Krikorian 在 Twitter 上发布内容的引用:
“与四年前不同,这次我使用 Java 作为重写的部分,而不是 Scala。一位工程师需要花两个月的时间才能充分高效率编写 Scala 代码。“
Paul Phillips 离开 Scale 的核心团队,他在一次长谈中对它进行了讨论,并绘制了一个恼人的语言状态图 - 与我们已知的形象形成鲜明的对比。
其中恼人的原因,你可以在这个 JSON AST 辩论中找到 Scala 社区的所有先驱。 读完之后的感觉就像这样:
在“Go”进入公众视野前,似乎没有真正可以替代 Scala 的语言。看看 Coursera 博客文章“为什么我们爱 Coursera 中的 Scala?”的节选:
“我个人发现编译和加载时间是可以接受的(它没有 PHP 编辑测试循环那么紧凑,但是相比于 Scala,我们可以接受其中的类型检查和其他细节)。”
这是另一个来自同一个博客的节选:
“Scala 确实很慢。并且,动态语言要求你不断地重新运行或测试代码,直到找出所有类型错误、语法错误和 null 反向引用。 ”
我们当中的一些人在 下班后的MOOC 上用6个月时间来学好 Scala ,而重新拾起“Go” 只要两周。实际上,我们第一次接触 Go 代码是在十个月前的一个 Code Retreat 上,那个时候我就能编写一个非常简单的 类似马里奥的游戏 了。
我们总是害怕低级语言,它们会强迫我们处理不必要的复杂层,其实这些只是在高级抽象的 Scala 中被隐藏了,例如:Futures 隐藏了 signal(信号),syscall(系统调用)和 mutexe(互斥器),不过这对于所谓的全栈开发者来说可能并不算什么事。
自古以来,当我们不确定怎么让某些东西工作的时候就会阅读 语言规范。很简单对吧,规范很好懂的!对于我这样的普通人来说意义非凡。我对 Scala(和 Java) 不满意的是看不到一个问题的完整上下文,因为它太复杂了。在看代码时,一份亲切完整的指导手册应该能在我对语言进行臆测时给我信心,并成为印证我决断正确与否的准则。
没有 map,没有 flatMap,没有 fold,没有泛型(generics),没有继承(inheritance)......我们是错过了他们吗?而让我们去做,大概只要两周。
我们一时半会说不清为何它在没有借鉴 Go 的情况下,也具有良好的表现力。但无论如何,Russ Cox,Golang 的领导者在 “Go 的平衡” 上做得很好(详情请看他在 2015 年写的 keynote)。
事实证明,在没有约束的情况下写出的代码,会让他人难以理解,无法把握其中的逻辑。反过来说,有人也会因为理解了别人无法理解的代码而自命不凡。但从动力学上来看,这种公开考量智力的事并不利于团队的发展,而当复杂的代码出现时,这种情况又在所难免。
从代码复杂性的角度来说,这不仅仅针对我们的团队;很多非常聪明的人都会这样做(持续去做)直到走向极端。有趣的是,因为在 Scala-land(也包括 Java-land)上依赖地狱无处不在,在我们最终使用一些工程的时候,我们就会觉得我们的代码库太复杂(例如:scalaz)了,因为它们出现了传递依赖。
这些例子随机选自我们使用(持续维护)的 Scala 库:Strong Syntax(你能明白文件的目的是什么吗?)Content Type(在 Github 上已经停止维护)Abstract Table(你能给我解释一下外键的签名吗?)
Channel 和 goroutine 在 资源管理上比基于 Future 和 Promise 的线程池更轻,这是不争的事实。编码时也更容易理解。
总结一下,我认为两种语言基于两种不同的方式基本上做了一样的工作,最后目的是一样的。“Go”简单的原因可能是它的工具集有限,你在反复使用之后就掌握了。而 Scala 的选项演变频繁,很难精通它的技术。
Go 的运行速度很快。
我们发现 Go 微服务非常适合分布式系统。
可从以下需要来考虑它有多适合:
● 小型容器:我们的 Go docker 容器平均大小是 16.5MB,Scala 是 220MB
● 低内存占用:方式可能会有不同;最近,我们取得了一个重大的成功就是在一个很糟糕的场景使用中, 实现了一个重要的每毫秒(μs)内存占用从 Scala 的 4G 变为 Go 所需的 300M
● 快速开启及快速关闭:只需一个可执行文件;并不需要启动一个虚拟机
臃肿的 Scala 镜像文件除了在云服务上花费很高,更关键的是部署到容器会产生延迟。重新计划一个 Kubernetes 节点的容器需要从一个已注册的点重新拉取镜像;镜像越大,花费的时间就越大。更不用说要把最新的镜像拉到我们本地的笔记本中
最后:工具
现在已经有很多 IDE 了:
Go都能用!工具正在抓紧时间稳步改善,新工具也在不断出现。
但是我个人最希望我们的 GO 能够崛起:我们要有我们自己的工具!
马全一,目前就职于华为技术有限公司中央软件院,华为 FusionStage 产品 DevOps 首席架构师,开源技术专家和布道师。国内早期 Container 技术推动者,Golang 语言忠实拥趸者。第一次在业界提出了 DevOps Orchestration 的理念,并用 Golang 语言实现了一个开源版本 ContainerOps (
2013 年开始研究 Docker 的时候第一次接触到 Golang 语言。由于一直工作在容器领域,接触到项目绝大多数都是 Golang 语言开发的,Golang 可以算是Cloud Native 领域的基石。2014 年的时候 Docker 的 Registry 还是用Python 语言开发,自己根据 Docker Registry 的协议,用 Golang 语言做了一个开源版本的实现。随着 Docker Registry 协议的不停变换,一直维护一个独立实现的版本,后续也支持 CoreOS 的 rkt 等其它容器引擎,现在这个项目落地成为华为 FusionStage 中的软件仓库。
在写 Golang 之前的 2 年一直是用 NodeJS 开发游戏相关的系统,一直被 NodeJS 的异步回调折磨。当使用Golang 时惊喜的发现语法非常简洁,学习曲线很平,使用 goroutine 很容易写出高并发的程序。但是 Golang 的包管理机制一直不太好,社区有不少的实现方案,都不能形成标准,希望在后续的版本中,Golang 官方的 Vendor能够更完善。
“Golang 的语言特性都很优雅,对我来说 Golang 语言的最大优势是代码非常易读,语法特性能够让整个团队很容易形成统一风格的代码,这对一个大型项目来说是非常重要的。”
孙建波,七牛的大数据研发工程师,参与了七牛的大数据平台整条链路多模块的架构设计以及开发工作,包括流式处理服务、时序数据库服务以及日志检索服务。在此之前主要研究和参与Cloudfoundry、Kubernetes、Docker等容器与容器云相关工作,是《Docker容器与容器云》一书的主要作者之一。
从2013年开始研究和学习使用PaaS云平台,那时候看到Cloudfoundry开始整个用Golang重构了一遍原来Ruby的实现,就对Golang 产生了很大的兴趣。后来越来越多的云计算项目用到Golang,自己也因为学习和研究阅读了一些开源项目(etcd\kubernetes\docker等),被Golang简单务实的风格吸引,成为了Golang的忠实用户。
在我看来Golang最大的特性是简单务实,这个简单包含的内容很多,比如接口(interface)的设定,只要实现了对应的方法就能作为那一类型的接口调用,去掉了复杂的对象继承关系;比如说goroutine以及channel的设计,你很难找到一个语言像Golang这么自然而轻易的支持并发编程;比如说代码包的引用方法,通过go get你几乎可以无障碍的获取和使用任意一个第三方库; 这个简单还包括上手快,一个对Golang零基础的工程师基本也能一眼看懂Golang代码。务实指的是他不提供一大堆花里胡哨的封装,但是它却愿意为工程化提供最大的便利,比如统一的代码格式化、测试的小工具等等。还有Golang官方提供的最大的承诺,1.0后永远向前兼容,保证了工程代码的可维护性。
有赞技术专家李文
李文, 目前杭州有赞技术专家, 目前负责消息队列系统的设计与实现,通过改造和加强NSQ为微服务架构打造基础消息组件. 另外负责的分布式KV系统也在紧张开发当中. 之前也做过分布式海量数据搜索系统和集群自动调度系统. 对分布式系统的开发有丰富的经验。
之前一直写C++, 也写过python, 一直对C++的开发效率不太满意, 希望能有python的开发效率. Golang的出现正好满足开发效率和语言特性的平衡, 在并发和分布式系统上面用Golang是明智选择. 当时正好有个proxy的小项目就拿来上手了, 惊讶于其高效率的开发, channel和goroutine的结合对这种网络连接管理类的项目简直是神器。
随着上手后, 逐渐开始接触Golang的生态系统, 对docker和调度相关的项目也在持续关注, 发现云计算领域的Golang使用还是很广泛的. 当时Kubernetes本身还刚刚开源, 功能还不够, 我们就先用Golang实现自己的调度器加了一些自己需要的功能, 现在随着时间的推移, docker和kubernetes都有了长足的发展, 可以看出Golang的生态圈发展之快令人兴奋. 后面随着CockroackDB和TiDB的发展进一步完善了Golang的生态圈. 这一段时间的发展, 让我看到了Golang的巨大潜力, 因此后面的项目一直是Golang做主力语言了.
当时还是Go 1.3, 那个时候有2个主要的不足令人困扰, 一个是依赖管理, 因为没有官方的支持, 出现了很多第三方的依赖管理, 方式各异令人头疼, 好在目前官方已经引入了依赖管理, 虽然有待完善. 另外一个就是GC的问题, 之前一直是Golang的不足, 但是后面3个大版本发布后, GC明显改进很多. 希望后面GC不光对latency关注, 也要关注GC的回收效率。
本周末(04-15 至 04-16)小谢在上海组织了一个 GoPher 大会,邀请各个领域的 Go 语言专家进行专题分享,主题非常诱人,比如:
Go 在大数据开发中的实战经验
Go coding in Go style
纯 Go 打造亿级实时分布式平台
Go 在百万亿级搜索引擎中的应用
等十几个主题。去不了现场也不用担心,这次极客邦和 GoPher 为工程师们提供了直播服务,你可以远程观摩这场大会。报名会员能够享有:
在线观看直播,有互动提问机会(建立专属微信群,即时提交问题给主持人,由谢孟军筛选并在大会现场进行提问);
会后第一时间收到大会 PPT 讲义;
会后学员可以在 StuQ 平台第一时间看到剪辑后的大会录播视频。
报名和观看直播的链接都是:
倒计时最后1天,再不抢座,难道你要把Go 语言大咖直面交流的机会拱手让人吗?
学习 Go 语言,长按二维码报名,看StuQ独家直播!
以上是关于为什么我放弃 Scala 选择Go?的主要内容,如果未能解决你的问题,请参考以下文章