在某乎上看到了這個問題, 仍是挺有意思的. 撕哪一個語言最好, 幾乎是工程師當中最好的引戰題目了. 今天我只想談談我是怎麼看待 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 也並沒以爲本身吃虧. 這不, 還能在這裏水一篇文章呢.