Go 語言誕生於谷歌,由計算機領域的三位宗師級大牛 Rob Pike、Ken Thompson 和 Robert Griesemer 寫成。由於出身名門,Go 在誕生之初就吸引了大批開發者的關注。誕生十年以來,已經湧出了很多基於 Go 的應用。就在不多久之前,知乎也捨棄了 Python,轉 用Go 重構推薦系統 。
谷歌前員工 Jake Wilson 認為,比起大家熟悉的 Python,Go 語言其實有很多優良特性,很多時候都可以代替 Python,他已經在很多任務中使用 Go 語言替代了 Python。那麼 Go 語言到底有著什麼樣的獨特魅力?它有哪些勝於 Python 的地方呢?讓我們一起來了解一下吧!
2019 年程序員最想學習的編程語言
![再見,Python!你好,Go語言](http://p2.ttnews.xyz/loading.gif)
image
出身名門的 Go 語言
對於一門只有十年曆史的新語言,Go 的發展勢頭相當迅猛,容器界的扛把子 Docker 就是用 Go 寫的,國內也有不少團隊廣泛使用 Go。近日,HackerRank 在社區發起了程序員技能調查,來自 100 多個國家、超過 70000 名開發者參與其中。調查結果顯示,2019 年,程序員最想學習的編程語言 Top 3 分別是 Go、Kotlin 和 Python,其中 Go 以 37.2% 的比例排在首位。
![再見,Python!你好,Go語言](http://p2.ttnews.xyz/loading.gif)
image
但 Go 要想撼動編程界的常青樹 Java 二十多年的地位無疑難度頗大。據 HackerRank 數據顯示,2018 年,Java 在開發者最受歡迎的編程語言排行榜中仍然排名第 2,Python 排名第 4,Go 排名第 13,距離第一名 JavaScript 還有不小的差距。
但對本文作者 Jack Wilson 來說,Go 語言雖然“年紀尚小”,但已經擁有很多非常優秀的特性。
Go 語言到底好在哪?
在很多任務上,我已經用 Go 語言代替了 Python,舉幾個例子:
- 處理儲存在 S3 上的雲端日誌
- 在 S3 上的 bucket 和 / 或 region 之間移動 TB 級別大小的文件
- 匹配本地的數據庫記錄和 S3 上的文件,以保證文件處於同步狀態
這些任務大多是一次性的,所以使用腳本語言操作就會比較合適。這些任務需要快速地編程,而代碼用過一次一般就捨棄了。一般來說,這種任務的需求都比較新穎、比較專,其代碼很少需要複用。下面就來介紹一下,針對這種任務為什麼可以用 Go 語言來替代 Python。
擁有編譯器很方便
我經常在寫 Python 時犯很低級的錯誤。我會給變量或函數命錯名,或向它們傳遞錯誤的參數。這樣的錯誤用調試工具可以找出一部分,但這種工具一般需要專門設置。我從來沒很方便地配置過 pylint,而且我也不喜歡用那些很重的、配置起來更麻煩的 IDE。最慘的情況是,你可能會不小心打錯變量名,而這種錯誤又不太容易發現。你的腳本可能會跑好幾個小時才遇上這個錯誤,然後一切都崩潰了,你又得從頭開始跑這個腳本。這種錯誤大部分都可以靠單元測試檢出,但單元測試很少能覆蓋 100% 的代碼,而且我並不想浪費時間去給一個只用一次的腳本寫單元測試。而帶編譯器的語言就可以解決以上所有問題。編譯器可以檢測出你犯的所有低級錯誤。出於這點原因,我在寫長達幾百行的代碼時,更傾向於使用 Go 這類語言。
開發速度
然而,需要編譯的語言的一個缺點是,一般你的開發速度會下降。這點在 C/C++ 和 Java 等語言上體現得尤其明顯。而 Go 是一個非常簡單的語言,我發現它的開發速度並沒有被拖慢多少。不要誤會,我的意思並不是說它比 Python 還快,而是想說,
用 Go 語言沒有比 Python 慢很多,一般達到使用 Python 開發速度的 85% 還是沒問題的。相對於擁有編譯器能避免的那些低級錯誤來說,我認為犧牲 15% 的開發速度還是很值的。更好的並行性
你可能已經知道,Go 語言就是為並行而生的。在我的團隊裡經常會需要並行程序,因為我們要在 S3 上操作我們數據庫中大量的數據。如果該任務是 IO 密集型的(實際上很多任務都是),我們就可以很容易地部署 Python 線程。但如果任務是 CPU 密集型的,用 Python 就比較不方便了,因為有全局解釋器鎖的存在。我非常享受在 Go 語言中簡單代碼不用修改就能直接多線程運行的爽快感。不知你在 Python 中有沒有遇到過這種問題:直接複製粘貼的多線程代碼卻完全不工作。在 Go 語言中就不會有此問題。
部署簡單
我比較喜歡把所有依賴放在單個二進制文件裡。我經常在 EC2 服務器上運行自己的腳本,好讓環境更加接近我們在 S3 上的服務器。如果用 Python 的話,我需要保證所有需要的包都在服務器上裝好,而且我的同事不能在服務器上裝任何可能產生衝突的包。虛擬環境可以解決大部分問題,但我還是覺得用 Go 語言更方便。我一般是在 Mac 和 Linux 上交叉編譯我的代碼,將其拷貝到遠程服務器上,然後就可以任其運行了。我的代碼所需要的所有依賴都在一個二進制文件裡。
風格一致
一開始,Go 語言的格式化工具 gofmt 實在是讓我抓狂,尤其是它在代碼縮進時要求使用 tab 鍵而不是空格鍵。我覺得這簡直是瘋了。但是我用了一段時間後,就開始“真香”了。寫代碼時,我在格式上可以天馬行空,格式化工具會幫我完成一切。我的所有代碼風格都是一致的,即使我是在寫不同的項目。這是因為格式化是標準 Go 工具的一個特性。但我如果想在 Python 中實現這一點,就要費些勁兒了。我需要正確地配置 pylint 工具,並要保證在每一個項目中都使用它。
更便捷的工具
Gofmt 只是 Go 語言眾多工具中的一個小例子。所有我喜歡用的編輯器——VSCode,vim 和 Sublime Text 中,都有 Go 語言相應的擴展,讓我能夠方便地享受到 Go 工具的優點。這樣,我就能獲得寫 Java 時的那種智能體驗,卻不需要真正使用一個 IDE。我在用 Python 時從未獲得過這種體驗。
Go 語言當然也有缺點
我每次看到批評 Go 語言的文章時,裡面講的幾乎都是 Go 語言對關鍵特性的缺失,比如泛型。我倒是認為沒有泛型沒什麼影響——你會發現,使用map和切片(Slice)就能實現多得驚人的操作。但是我在使用 Go 語言的過程中遇到了很多其他問題。
缺乏靈活性
首先,Go 語言可能是我用過的語言裡最“固執”的語言了。比如,它除了會強迫你使用 tab 而不是空格鍵縮進(假設你用了 gofmt 工具),會強迫你使用特定的文件組織結構,還會強迫你在 GOPATH 環境變量中編程,如此等等。這種語言有太多難以改變的特性了。Go 語言簡單易學的原因之一恐怕就是你不能改變這些特性。如果你不願意將所有首字母大寫的變量名 export 一遍,那真是抱歉了。幸運的是,Go 的這些特性倒是沒有觸犯我的原則底線,但是如果有人認為裡面的某些要求根本無法理喻,我也能夠理解。相比之下 Python 就靈活多了。
庫支持有點差勁
在這方面把 Go 語言和 Python 做比較有些不公平。Go 的出現比 Python 晚很多,但當我發現有些功能 Go 居然不支持的時候,還是覺得很困惑。我甚至發現 StackOverflow 上很多人 po 出了本應該作為內置功能的代碼段,而且大家都需要該功能,紛紛將代碼複製粘貼到自己的項目下。這類功能不應該嵌入到語言內部嗎?說到這裡,我想到了近幾年的兩個例子:
- 給切片排序(幸運的是在 Go 1.8 版本中這點方便多了)
- Math.round 只支持整數,不能進行浮點數的取整(比如你想找一個最接近 0.5 的整數,Go 語言就無法完成)。甚至在 Go 1.10 版本之前,根本沒有 math.round 函數
當然,這些問題的原因有一部分是 Go 語言沒有泛型,另一部分是因為 Go 的開發者們只給 Go 的標準庫中添加最最必要的功能。
這兩點我都理解,但是在遇到很小的問題卻需要自己寫代碼解決時還是感到煩惱。希望隨著 Go 語言的發展,它的問題會變得越來越少。
Go 和 Python 你更喜歡誰?歡迎留言交流!
在接觸Golang以前,我用C/C++、Lua及Python作為主要開發語言。
C/C++的問題:
- 開發效率低,對開發者要求高
- libc只向後兼容,運維難度偏大
Lua/Python的問題:
- 動態語言,缺少編譯過程,低級錯誤頻出
- 缺少有效的性能分析及調試工具
** 場景**
當時剛完成了nginx WAF模塊的開發工作,便開始著手搭建WAF的後臺管理系統。 由於之前同事都用的fluentd作為日誌收集組件,為保持基礎組件的一致性,我也選擇了fluentd。 即最終架構為fluentd->mongodb->mysql,再基於mysql做前端數據展示。 後來被坑了許多次,就決定用Go重寫fluentd以解決下面幾個問題:
- fluentd在ubuntu 9.04偶爾會出現假死,導致數據丟失
- fluentd難以接入公司現有的包發佈系統,導致運維難度極大
- mongodb採用mmap實現,數據量大時佔用內存過高
方案
- gofluent的代碼 請點擊這裡
- httpmq的代碼 請點擊這裡
事實上,這兩個項目都是為了解決上面提到的問題。 說起來也許你不信,這兩個套代碼是我在業餘時間完成的,也就是說這根本不算在KPI之內。 其實一開始我也沒想到能夠這麼快就寫得七七八八,畢竟是現學現用啊。 但實際情況就是,我花了一週時間寫完httpmq,一個月多時間就寫好了gofluent……當然,這兩個項目還有很多不完善的地方。目前就日誌收集方案來說,我更推薦elastic/logstash-forwarder · GitHub和elastic/logstash · GitHub配合使用。
為什麼選擇Golang
那麼,為什麼我會選擇Golang呢?其實我在做出這個選擇之前已經花了大量時間做過詳盡調研。 國外如Google、AWS、Cloudflare、CoreOS等,國內如七牛、阿里等都已經開始大規模使用Golang開發其雲計算相關產品。 跟著世界級巨人的腳步應該不至於走錯方向,而且在學習Golang的過程中,我也漸漸被其背後的設計哲學所折服。
另外,雲風博客中曾說過這樣一句話:
我發現我花了四年時間錘鍊自己用 C 語言構建系統的能力,試圖找到一個規範,可以更好的編寫軟件。結果發現只是對 Go 的模仿。缺乏語言層面的支持,只能是一個拙劣的模仿。
以下則是我對Golang的淺薄理解:
- 有C基礎,學Golang非常輕鬆
- 同步方式輕鬆實現高併發
- 代碼簡潔,格式統一,閱讀方便
- 性能強勁的同時,開發效率又不差於Python等動態語言
效果
最開始準備上線的時候其實心裡挺忐忑,畢竟一旦出現故障,不僅黑鍋得自己背,面子也上過不去啊。 還好結果蠻漂亮,自上線後沒出現過一次突發性BUG,降低運維難度的同時還減少了機器的負載。
總而言之,從工程的角度上來看,對於大多數後臺應用場景,選擇Golang是極為明智的選擇。 這樣可以很輕鬆的兼顧運行性能、開發效率及維護難度這三大讓諸多程序猿欲仙欲死的奇點。
閱讀更多 guorenweitianxia 的文章