在某乎上看到了这个问题, 仍是挺有意思的. 撕哪一个语言最好, 几乎是工程师当中最好的引战题目了. 今天我只想谈谈我是怎么看待 Go 的, 以及我走的一些弯路.html
我是 2010 年在学校的时候了解到 Go 语言的. 当时的 Go 语言仍是一塌糊涂, STW GC 是你们嘲讽 Go 语言的最佳标靶. 只要黑一句, Go 粉基本被噎得说不出话来.nginx
我当时正想储备一门带并发编程模型的语言. 由于以为将来 CPU 主频再也不增加的状况下, 带并发编程模型的语言确定是将来的主流. 是共享内存型语言强有力的竞争对手.git
候选名单以下:github
Erlang, Golang, Scala 搭配 Akka.web
首先 Scala 被我排除掉了, 由于 Akka 的实现我以为并很差, 并且当时 Scala 并无本质上的重量级应用 ( Spark 虽然在 2010 年开源了, 可是真正流行起来要到2012年后了 ). 其次就是 Go 和 Erlang 了.docker
当时我对 Erlang 很是痴迷, 由于 Erlang 是惟一一个实现了软实时调度器的编程语言. 这意味着这东西能够直接用来写电话交换机 ( 固然 Erlang 诞生之初也是为了这个目标而存在的 ), 而若是要用Go来写电话交换机, 极可能会电话打着打着, 碰到了 STW GC, 而后你就听不到电话对面在讲什么了 ( 这也是为何后来 WhatsApp 用了 Erlang, 50 个工程师写出了支撑 9 亿用户的系统 ).shell
并且, Erlang 实现的系统, 作到了 9 个 9 的可用性. 这是什么概念? 这意味着整年停机时间不超过 31.56 毫秒. 几乎就是不会停机了. 阿里云都只能说本身的可靠性 6 个 9, AWS 的可用性只有 99.95%. 意味着每一年要停机 4.5 小时左右.编程
Erlang 另一个设计的好的地方是, 它自己的 runtime 与其说是虚拟机, 不如说是操做系统, 是个运行时容器. 要知道 BEAM ( Erlang 虚拟机的名称 ) 在1992年就被实现了. 而 Docker 2013 年才出现. 这是多么超前的理念.缓存
因而我义无反顾的学了 Erlang, 而 Golang 我只是看了看语法, 写了几个 demo, 观望了下.websocket
时间来到了 2012年, 我去 360 搜索实习. 我被分配的一个任务就是写一个监控程序, 实时收集并展现 nginx 的链接数等状态, 作数据可视化供运维工程师调度机器参考. 机器的数量很是多, 而且要实时展现, 这算是个难点. 我马上想到了用 Erlang 写, 这简直是为 Erlang 量身定作的场景.
我写完了, 而且顺利的实现了功能. 这时候收到的反馈是, 写得很棒, 可是公司没有用 Erlang 的工程师, 没办法维护, 因此在建议下我又用 Node.js 的 websocket 和 Redis 的订阅机制实现了个伪实时的监控系统... 这是我第一次, 也是最后一次用 Erlang 给企业写应用.
是的, Erlang 输在了这里. Erlang 的发明者 Joe Armstrong 有一篇文章 solving-the-wrong-problem 开头第一句就说了这么一句话:
We're right and the rest of the world is wrong. We (that is Erlang folks) are solving the right problem, the rest of the world (non Erlang people) are solving the wrong problem.
如今来看, 这句话简直太中二了, 大意就是, 错的不是我, 是世界.
Erlang 为何没有在 CPU 主频没法继续提高, 而核心数猛增的这么好的生态下火起来. 这个问题其实大佬早就说过了. Erlang 也不是惟一一个倒下去的例子. Richard P. Gabriel ( Common Lisp的发明者之一 ) 在这篇文章中 The Rise of Worse is Better 很好地阐述了为何 Lisp 会没人用, 这个道理一样适用于 Erlang 身上.
简单来说就是, Erlang 太好了, 为了完美的解决问题致使设计的很难学很难使用. 曲高和寡. 而那些简单好用的垃圾, 才能流行起来.
很合理, 这个道理再简单不过了. 这也是为何你们不去看书, 而是喜欢去听喜马拉雅听, 喜欢去看知乎, 喜欢去看掘金, 喜欢这些被咀嚼一遍的东西, 以为学到了知识. 由于对你们来讲, 看书太难了, 太痛苦了.
但当时我年轻啊, 以为那好办, 我此次选个最简单的, 因而我又跟风学了 Lua (openresty). 这个却是很简单, 我是看左耳朵耗子老师那篇 LUA简明教程 入门的. 个人确是在厕所蹲坑的时间就学会了, 不到 1 小时 ( 有 JavaScript 经验的同窗会更快一些 ). 而后写了不少个支持单机 10 万+级别并发的应用 ( 好比熊猫TV直播间的右侧礼物排行榜, 好比掘金的全局数据缓存等等 ).
但 Golang 也有了相似解决方案. fasthttp 做为 Go 的表明型高性能WEB框架, 轻松也能够支持 10 万级别的并发.
是时间不等人. Golang 在 10 年时间, 成为了怪物. 不但 STW GC 的问题解决了 ( 固然仍是比不上软实时的 GC 那么平滑 ), 并且有了 kubernetes 这样的可怕的杀手锏. 也许有同窗不理解 kubernetes 的可怕. 将来, 你们写的程序极可能既不是直接运行在物理机上, 也不是运行在 Xen, VMWare 等虚拟机上, 而是都会运行在 Docker 上, 由 kubernetes 进行调度. 甚至连选择的权利都没有 ( 不相信的同窗能够问问在大厂的同窗, 他们有本身部署目标机的 root 权限么 ).
看到这里, 是否是很熟悉? Erlang 早都实现了这一切, 甚至调度粒度更细, Erlang 实现了内置进程 ( 相似 goroutine ) 级别的调度. 而 Golang 的 goroutine 可不能跨 Docker 调度吧? ( 虽然说接个网络通讯模拟下也能实现相似的东西 ) . Erlang 提出了 Let it Crash 的概念. 如今看看 kubernetes 疯狂重启你的 docker pod, 是否是似曾相识?
openresty 也说明明是我先的 ( 白学现场 ), openresty 诞生之初, 能轻松支持 10 万级别并发访问的WEB框架屈指可数. 但如今 Golang 也能够了. 甚至更好 ( 少背了个 nginx 这么大个包袱 ).
读到这里, 你也许会问, 你这么做死, 每次几乎都选错了, 怎么还能混口饭吃? 那我只能说, 我编程的入门语言是 PHP, 这玩意比 Golang 还 New Jersey Style. 让我能找到工做的也是 PHP. 而我却在别的语言上持续做死. ......哈哈哈哈...... 这还真是悲哀.
有正在用 PHP 同窗也许会问, 那么学 swoole 合适吗? 个人建议是. 都是成年人了, 不要作选择, 全都要. 不管是 swoole, fasthttp, netty, 都值得你看. 我学了 Erlang 也并没以为本身吃亏. 这不, 还能在这里水一篇文章呢.