近日,Python 被納入全國電腦等級考試科目、編入了小學教材、獲得了 2018 年頂級程式設計語言榮譽,可以說,Python 要多火就有多火。而本文並非為此火上添油,而是適時地為 Python 澆了一盆涼水,穩步發展才是一門程式設計語言的正軌。本文作者使用了 Go 語言完成了曾經用 Python 搞定的多種任務,對比發現,Go 語言的方法似乎更勝一籌。
其中,完成的任務比如說:
處理 S3 上儲存的 Cloudfront 日誌;
在 S3 中將 TB 層級的資料從一個桶移到另一個桶,或者其他地區;
比較資料庫中的資料和 S3 中的檔案,確保資料的同步。
許多都是一次性的任務,因此指令碼語言很合適。程式要能很快寫出來,而且基本上用完就不會再用了。通常每次任務都是全新並且唯一的,因此幾乎沒有代碼重用的可能。
下面是 Go 比 Python 強的地方:
編譯器很好
我在 Python 中一直犯愚蠢的錯誤。比如搞錯變數名或函數名,或者給函數傳遞錯誤的參數。Devtools 能發現一些錯誤,但通常這些工具需要特別設定。我從來沒能完美設定好 pylint,我也不喜歡那些需要單獨配置的笨重的 IDE。
最糟糕的情況是隱藏在條件邏輯後面的錯誤變數名。代碼會運行幾個小時,直到錯誤觸發。然後就不得不一切從頭開始。
單元測試通常能捕獲這些錯誤,但很難獲得 100% 的程式碼涵蓋範圍,而且對於一次性的指令碼我也不想浪費時間寫測試。
編譯語言能完全避免這些問題。編譯器能找出所有愚蠢的錯誤。因此,對於任何超過 100 行代碼的任務,我更喜歡使用 Go。
開發速度
編譯器的缺點就是通常會降低開發速度。尤其在 C/C++ 和 Java 上特別明顯。
但 Go 非常簡單,我發現它對開發速度的影響非常小。不要誤會,我用 Python 依然更快,但用 Go 通常能達到 Python 的 85% 效率。
考慮到使用編譯器能犯更少的錯誤,85% 已經非常值得了。
更好的並發性
你一定知道,Go 的開發目的就是並發執行。
在我的團隊中我們一般都需要並發編程,因為我們要處理 S3 或資料庫中的海量資料。
如果任務中有很多 IO(許多任務都是如此),那我們可以用 Python 的線程。但如果需要很多 CPU,那 Python 就很難辦,因為它有全域解譯器鎖(Global Interpreter Lock)。
而使用 Go 的多線程,無需任何特殊處理就能正常工作,這一點非常棒。你一定體會過在 Python 中按 Ctrl-C 試圖結束多線程任務卻毫無反應的情況吧?
更容易部署
我喜歡單一的二進位檔案。通常我在 EC2 機器上運行代碼,使之在網路上更靠近與 S3 和資料庫。使用 Python,我需要在遠程機器上安裝所有的包,並確保其他人沒有安裝任何衝突的東西。
雖然 Virtualenv 能解決這個問題,但我依然認為 Go 更容易。
通常我會在我的 Mac 上將代碼交叉編譯成 Linux 二進位檔案,然後複製到遠程機器上,然後就可以執行了。所有依賴都被放到二進位檔案中了。
一致的風格
最初,gofmt 工具的確挺煩人,特別是他們使用 tab 而不是使用空格。我認為他們簡直是瘋了。
但用得多了後,我開始依賴它了。它能直接提供完美的代碼格式。不管是哪個項目,所有代碼都有同樣的風格,因為風格就是標準 Go 工具鏈中的一部分。
而在 Python 中達到同樣的效果需要更多的功夫。必須正確配置 pylint,並保證每個項目的配置都是一樣的。
更好的工具鏈
gofmt 只是通用工具鏈的一個例子。所有我喜歡的編輯器,不論是 VSCode、vim 還是 SublimeText,都有非常好用的 Go 語言擴充,使用標準的 Go 工具鏈。
因此,我能獲得近似 Java 的只能提示,但無需使用真正的 IDE。而使用 Python 就從來沒能享受過這樣的功能。
缺點
我讀到的許多批評 Go 語言的文章都在說它缺乏某個明顯的功能,比如泛型。但沒有泛型我也從來沒遇到過麻煩。實際上 map 和 slice 能完成許多工作。不過我卻有些其他的問題。
Go 是有觀點的語言
首先,Go 可能是我用過的最有觀點(opinioned)的語言了。從強迫使用 Tab 而不是空格(假設你用 gofmt),到強迫使用固定的目錄格式,甚至強迫在GOPATH 環境變數中寫代碼,許多 Go 的東西都沒辦法改變。
有觀點的理由之一就是這樣易於學習,因為這些特點都不會改變。但如果你不想匯出的名字以大寫字母開頭,那就沒辦法了。不過幸運的是,這些問題都不會成為我不使用 Go 的理由,但我能理解有些人無法接受。
而 Python 則更靈活。
缺乏庫支援
在這個領域比較 Python 和 Go 並不太公平。Go 非常年輕,但我還是會在發現 Go 本身不支援某個功能時感到很不解。更讓我失望的是,一些人在 StackOverfolw 上貼了些本應是內建函數的代碼,然後每個人都彷彿沒事兒一樣直接把代碼粘貼到項目裡使用。
舉兩個近幾年我發現的例子:
對 slice 排序(幸運的是在 Go 1.8 中變得容易得多了)
math.round 只能用於整數,而不能四捨五入成浮點數(比如四捨五入到最近的.5)。甚至在 Go 1.10 之前都沒有 math.round。
當然,一些原因是因為 Go 沒有泛型,一些是因為 Go 的設計思想就是只把絕對必要的東西加到標準庫中。
我理解這兩個原因,不過在遇到非常簡單的功能卻不得不自己寫代碼時還是覺得很煩人。
希望 Go 語言能越來越好,痛點能越來越少。
原文:thinkfaster.co/2018/07/goo…譯文:CSDN資訊作者:Jake Wilson譯者:彎月,責編:屠敏
CSDN學院GO語言課程推薦:
1.go語言實戰—詳細的golang教程
2.Go語言-基礎篇
3.Go語言-進階篇