如何客觀的評價 Go 語言

新年快快發表於2019-04-21

我是從 2015 年開始接觸 Golang,並在之後開始在某出行公司的線上環境大規模使用,同時個人還利用個人時間深入研究過 Golang 的底層實現機制,包括記憶體管理、GC 機制、Runtime Scheduler、Interface、Channel 等。這篇文章力求客觀的討論一下 Golang 的利弊。

優點

1. 簡單

簡單應該是 Golang 最大的優勢。Golang 的語言特性簡單,學習週期短,熟悉其他程式語言的開發者基本都可以在短時間學會並寫出各方面都還不錯的程式碼。所謂各方面都還不錯是說新手開發者寫出來的程式碼和一些有經驗的開發者寫出來的程式碼差別並不會太大。

Golang 語言層面上的簡潔性讓一些新手程式設計師也能寫出效能不錯,bug 不多的程式,這個相比其他高階語言,比如 C++,是一個非常大的提升。MIT 的一個非常有名的課程 6.824 最開始使用功能的 C++,後來改成了 Golang,就是為了讓大家可以專注於分散式演算法本身,而不是陷入到語言細節的除錯當中去。

2. 兼顧開發效率和效能

Golang 由於豐富的原生庫和周邊生態的支援,開發效率甚至可以比肩 Python。很多公司早期,或者專案早期的時候為了趕開發進度都會將開發效率放在第一位,比如 Python,PHP 這種動態語言。但是動態語言的效能劣勢非常明顯。現在的一個好現象就是 Golang 已經越來越多的被小公司採用了,畢竟寫一個 http server 不過三行程式碼。

另外在開發效率的前提下,Golang 還具有非常高的效能。這一方面得益於靜態語言,另一方面和其本身的語言設計也有很多關係。但是這裡說的非常高的效能有點不太嚴謹,相比 C++/Java 這種老牌的高階語言,在某些場景下的 benchmark 還是要略遜一籌的。

3. 語言級別的特性支援

所謂語言級別的併發支援,就是使用 go func 直接啟動一個 goroutine,外加 select/chan 等周邊。在沒有語言級別的支援之前的非同步程式設計簡直就是 callback 噩夢。記得雲風大神之前對 Golang 的一段評價: 我發現我花了四年時間錘鍊自己用 C 語言構建系統的能力,試圖找到一個規範,可以更好的編寫軟體。結果發現只是對 Go 的模仿。缺乏語言層面的支援,只能是一個拙劣的模仿。 雲風 現在很多人使用一門新語言的時候,有時候還會問:“有對應的 coroutine 庫嗎?” Golang 的語言層面的支援極大的解放了開發者的心智負擔。

缺點

1. runtime

支援 runtime 的程式語言一個無法繞開的問題就是 runtime 帶來的一系列問題,比如效能損耗。在 rust 語言介紹自己的優勢的時候有一點就是 no runtime。

Golang 的執行緒模型排程是 M:N,runtime 排程模型是 GMP 模型,偽搶佔式的。簡單點來說就是 runtime scheduler 可以類比成作業系統,但是缺乏硬體層面上對作業系統的支援,比如硬體中斷,這就對 sheduler 的設計要求的非常高,但是 Golang 的實現並沒有想象中的那麼好。

2. 並不能做到真正高併發高效能

Golang 的高併發使用原生庫來實現的話一般都是通過多 goroutine + select/channel,但是我們看 channel 原始碼,發現這個東西就是一個佇列+一把鎖。這也就意味著無法避免多個 goroutine 帶來的競爭問題。我之前測試過在多個 goroutine 競爭同一個 channel 的時候,效能急劇下降。所以很多高效能的高併發程式如果是用 Golang 來寫,很多都會避免使用 channel 來傳遞資料,而是借用類似 disruptor 的 ringbuffer 技術。

但是這並不是說 Golang 在高併發場景下效能不行,對於日常的 io 密集型的 web server,可以說效能是足夠了。

其他

這裡談一下 Golang 自問世以來一直被詬病的幾個問題。

1. GC

大概從 1.0 版本以來,GC 就一直被詬病。值得欣慰的是,Golang 的 GC 一直在發展,基本在每個版本都有一定的改進。1.8 版本是 GC 的一個里程碑,使用併發三色標記法的 GC 演算法的stw 時間甚至達到了微秒級。目前社群貌似在討論分代 GC 的方案,這個後面專門寫一篇文章細說。

2. 包管理

包管理也是一直被詬病,主要是一直沒有一個官方的解決方案。直到去年官方終於開始有行動了,推出了 module,相對來說還是一個很不錯的方案。

3. 泛型

Golang 沒有支援泛型的很大一個原因是泛型太複雜。儘管很多人說 interface 也能實現泛型功能,但是這個泛型還是有一些本質的區別的。沒有泛型確實是一個減分項。

最後,我們從下一篇文章開始瞭解 Golang 的一些重要特性和底層原理。

參考

  1. blog.golang.org/versioning-…
  2. blog.golang.org/modules2019

最後歡迎感興趣的同學關注微信公眾號。

如何客觀的評價 Go 語言

相關文章