有關GO和Erlang的一些思考
修正:我知道我沒有把本文的觀點表述清楚。我不會說GO語言有問題,或者它應該做些什麼改變,因為它跟Erlang語言不一樣。我準備說的是GO所做的選擇讓它難以與Erlang在實用性和低響應高併發需求的後臺應用上抗衡。有必要注意一下,我不會寫像Julia語言一樣的東西。我聽說不管是新專案還是老專案,GO都被定位為Erlang的競爭對手。沒有人會對JULIA語言說這樣的話,但GO和Node.js倒是被一些人看作是Erlang很好的替代品。Erlang不能解決所有的問題!本文主要談論的是哪些地方Erlang適合使用而GO卻不適合使用。
我打算不帶主觀意見,用公正的眼光來看待GO,先將自己對它不喜歡的部分遺忘,比如說語法或缺乏模式匹配,並且解釋語言本身和執行環境的型別系統的某些不適應的客觀原因。雖然它有很多缺點,但我打算先從其好的部分說起。
GO語言的亮點
客戶端
正如Rob Pike所寫的,它最大的驚喜就是GO語言吸引了許多Python和Ruby的開發人員,而不是C++的。對於我來說我很樂於看到這種趨勢。不再有用pip和gems安裝的執行速度慢的客戶端了!(雖然由於某些原因Node.js用於客戶端的人數在增加,TMD keybase呢?)
GO通過垃圾回收和併發原語能讓開發人員快速,簡單的使用高階,靜態語言。同樣地,這也可能是C++轉戰GO的一個重要因素,在我電腦上跑著的程式(Hipchat和Spotify)經常崩潰都是因為C++喜歡濫用記憶體。但Rob Pike指出C++的開發人員不想使用簡單強大的GO語言。但Ruby和Python開發人員很樂意轉戰GO。
工具
在不依賴於第三方工具的情況下能輕鬆使用第三方庫來構建可執行檔案,這都是GO的亮點。雖然這些工具不太完美,但有一些工具能彌補這些缺點,比如說Godep。對於GO來說這也是一大勝利。
GO的不足之處
當GO被用來寫低延遲容錯系統的時候,它的一些設計決策是有害的。
併發性
是的,在第一部分我已經額外的提到了併發原語。這是GO在替代Ruby,Python或C++作為客戶端語言的情況下作出的說明。但當需要寫容錯的後臺程式時,在共享狀態方面GO和其它語言一樣爛。
搶佔式排程
在這方面GO語言要好一些。GO語言的搶佔式排程是針對系統呼叫的,但現在,當goroutine檢查所有函式呼叫的堆疊時搶佔就能發生,如果goroutine的執行週期比以前的長,那麼這很可能會被標記為失敗(這將會造成搶佔)。雖然這是一種進步,但還是滯後於Erlang的減少計算和最近為改進C整合而新增的髒排程。
垃圾收集
在GO中垃圾收集是全域性標記和清理垃圾的。在清理垃圾時會暫停所有的goroutine,而且等待時間很恐怖。低等待時間是很困難的,執行時間越長,它就能為你做的越好。
錯誤處理
如果返回值為nil,不僅僅只是沒有異常和使用檢查。Goroutine沒有身份標識,這意味著GO缺乏連線和監控goroutine的能力。沒有連線(它使用的是panic和defer)和程式隔離,意味著你不能以穩定的狀態避免當機和重啟。在產品中會有BUG,而且許多BUG都是Heisenbugs,所以能讓程式與程式之間隔離開來但要基於他們之間依賴,是容錯的關鍵。
在處理錯誤的重大遺漏上,GO有nil。它在2014年是如何被認為可以的,目前我腦海中還沒有任何概念。先不管它,稀裡糊塗的看看再說。
內省
沒有REPL對開發來說是一件惱人的事,但沒有遠端shell來執行系統是更讓人煩惱的事。Erlang有驕人的追蹤能力,一些工具是建立在這些能力上的,比如recon_trace。Erlang的內省很好的改善了開發,同時也能更好的維護複雜的系統。
靜態連結
是的,同樣積極正面的一個東西,但如果用在期望執行時間很長的系統上它就變得消極了。雖然沒有連結執行確實會比較慢,但這卻給了Erlang在執行系統上程式碼替換方面的優勢。很有必須說明一下,由於Erlang的排程和垃圾收集策略,許多這些速度權衡並不意味著Erlang在同樣的應用中會比其它語言慢,特別是如果Erlang應用是唯一一個仍在執行的。
程式碼組織
OTP框架為通用模式提供了庫。OTP不僅意味著更少的程式碼和更好的抽象,同時也意味著更好的可讀性。隨著應用的OTP標準,管理人員和工人(gen_server, gen_fsm, gen_event)意味著程式的新開發人員能夠通過程式樹很好的工作,同時也表明他們之間是如何互動的。GO的channel,不可識別的goroutine和缺乏模式將goroutine分割成獨立的模組會讓程式碼變得更難寫。
GO能改變、應該改變嗎?
Erlang已經問世數十年了,而GO是新產品,那麼GO能在這些領域得到改善嗎?有些地方是可以的,但由於語言設計本身缺乏容錯和低延遲,它在絕大地方都不能改善現狀。
這並不是說GO不好或者它設計得有誤。它的這些不同能讓其它像Erlang這樣的語言更好的解決不同的問題。
相關文章
- 關於DDD和COLA的一些總結和思考
- 關於2021年的一些收穫和思考
- 【Go】高效擷取字串的一些思考Go字串
- 關於CodeReview的一些思考View
- 關於 Masonry 的一些思考(下)
- iOS關於換膚和夜間模式的一些思考iOS模式
- 大魚思考---有關190億$的思考
- 關於在Interface和Abstract Class間選擇的一些思考
- 關於前端工程化(基建)的一些總結和思考前端
- 關於賬號安全的一些思考
- 關於 Go 程式碼結構的思考Go
- 關於作業系統的一些思考作業系統
- 關於REACT正規化的一些思考React
- 關於 12306 售票的一些思考研究
- 關於aspnetcore中介軟體的一些思考NetCore
- 關於微服務劃分的一些思考微服務
- 關於Code Review的一些思考總結View
- 關於近源滲透的一些思考
- 2020年的一些思考和總結
- 關於許可權系統的一些思考
- 關於研發規範化的一些思考
- 近期關於快取設計的一些思考快取
- Java Record 的一些思考 - 序列化相關Java
- 關於RxJava在業務上的一些思考RxJava
- 給年輕人的有關AIGC的資訊、思考和建議AIGC
- 關於Fork和Malloc的思考
- 關於typedef和struct使用過程中的一些思考(2020/12/23更新)Struct
- RabbitMQ與Erlang的版本對應關係MQ
- 關於模擬經營遊戲的一些思考遊戲
- 關於redis快取資料庫的一些思考Redis快取資料庫
- 關於React中動畫不生效的一些思考React動畫
- 整理了一些和PHP有關的技術大會PHP
- 生活的一些思考
- 視覺化搭建的一些思考和實踐視覺化
- rabbitMQ和對應的erlang版本匹配MQ
- 有關python的一些小知識Python
- 【vuejs】有關vue的一些小技巧VueJS
- 關於技術人員自身能力提升的一些思考
- 十問 TiDB :關於架構設計的一些思考TiDB架構