再見,Python!你好,Go語言

codeGoogle發表於2019-03-11

Go 語言誕生於谷歌,由計算機領域的三位宗師級大牛 Rob Pike、Ken Thompson 和 Robert Griesemer 寫成。由於出身名門,Go 在誕生之初就吸引了大批開發者的關注。誕生十年以來,已經湧出了很多基於 Go 的應用。就在不多久之前,知乎也捨棄了 Python,轉 用Go 重構推薦系統 。

作者:華為雲技術宅基地 連結:https://zhuanlan.zhihu.com/p/57895717

谷歌前員工 Jake Wilson 認為,比起大家熟悉的 Python,Go 語言其實有很多優良特性,很多時候都可以代替 Python,他已經在很多工中使用 Go 語言替代了 Python。那麼 Go 語言到底有著什麼樣的獨特魅力?它有哪些勝於 Python 的地方呢?讓我們一起來了解一下吧!

2019 年程式設計師最想學習的程式語言

image

出身名門的 Go 語言

對於一門只有十年曆史的新語言,Go 的發展勢頭相當迅猛,容器界的扛把子 Docker 就是用 Go 寫的,國內也有不少團隊廣泛使用 Go。近日,HackerRank 在社群發起了程式設計師技能調查,來自 100 多個國家、超過 70000 名開發者參與其中。調查結果顯示,2019 年,程式設計師最想學習的程式語言 Top 3 分別是 Go、Kotlin 和 Python,其中 Go 以 37.2% 的比例排在首位。

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實現,資料量大時佔用記憶體過高

方案

事實上,這兩個專案都是為了解決上面提到的問題。 說起來也許你不信,這兩個套程式碼是我在業餘時間完成的,也就是說這根本不算在KPI之內。 其實一開始我也沒想到能夠這麼快就寫得七七八八,畢竟是現學現用啊。 但實際情況就是,我花了一週時間寫完httpmq,一個月多時間就寫好了gofluent……當然,這兩個專案還有很多不完善的地方。目前就日誌收集方案來說,我更推薦elastic/logstash-forwarder · GitHubelastic/logstash · GitHub配合使用。

為什麼選擇Golang

那麼,為什麼我會選擇Golang呢?其實我在做出這個選擇之前已經花了大量時間做過詳盡調研。 國外如Google、AWS、Cloudflare、CoreOS等,國內如七牛、阿里等都已經開始大規模使用Golang開發其雲端計算相關產品。 跟著世界級巨人的腳步應該不至於走錯方向,而且在學習Golang的過程中,我也漸漸被其背後的設計哲學所折服。

另外,雲風部落格中曾說過這樣一句話:

我發現我花了四年時間錘鍊自己用 C 語言構建系統的能力,試圖找到一個規範,可以更好的編寫軟體。結果發現只是對 Go 的模仿。缺乏語言層面的支援,只能是一個拙劣的模仿。

以下則是我對Golang的淺薄理解:

  • 有C基礎,學Golang非常輕鬆
  • 同步方式輕鬆實現高併發
  • 程式碼簡潔,格式統一,閱讀方便
  • 效能強勁的同時,開發效率又不差於Python等動態語言

效果

最開始準備上線的時候其實心裡挺忐忑,畢竟一旦出現故障,不僅黑鍋得自己背,面子也上過不去啊。 還好結果蠻漂亮,自上線後沒出現過一次突發性BUG,降低運維難度的同時還減少了機器的負載。

總而言之,從工程的角度上來看,對於大多數後臺應用場景,選擇Golang是極為明智的選擇。 這樣可以很輕鬆的兼顧執行效能、開發效率及維護難度這三大讓諸多程式猿欲仙欲死的奇點。

閱讀更多

資本寒冬下的android面經

程式設計時,照著別人的程式碼敲進去有效率嗎?

開發了5年android,我開始了go學習之旅

2018 開發者生態報告:Java 最流行,Go 最有潛力,JavaScript最常用

最後, 我還是建議你在這個網際網路時代裡,不要刻意追求一種語言,每一種語言都是有他的優勢,選擇合適的才是最重要的。網際網路沒有過期的技術,也沒有寒冷的冬天。我們選擇儘可能多的儲備糧食柴火。歡迎關注我微信技術號:終端研發部,id:codeGoogler。如果您遇到什麼問題,也可以和我一塊交流~

相關文章