[譯] 為什麼你要學習 Go?
- 原文地址:Why should you learn Go?
- 原文作者:Keval Patel
- 譯文出自:掘金翻譯計劃
- 本文永久連結:github.com/xitu/gold-m…
- 譯者:todaycoder001
- 校對者:TokenJan,JackEggie
為什麼你要學習 Go?
“Go will be the server language of the future.” — Tobias Lütke,Shopify
在過去幾年,有一門崛起的新語言:Go 或者 GoLang。沒有什麼比一門新的程式語言更令開發者興奮了,不是麼? 因此,我在 4、5 個月之前開始學習 Go。在這裡我將告訴你,你為什麼也要學習這門新語言。
在這篇文章中,我不打算教你怎樣寫 “Hello World!!”。網上有許多其他的文章會教你。**我將闡述軟硬體發展的現狀以及為什麼我們要學習像 Go 這樣的新語言?**因為如果沒有任何問題,我們就不需要解決方案,不是麼?
硬體的侷限性
摩爾定律正在失效。
英特爾公司在 2004 年推出了第一款具有 3.0 GHz時鐘速度的奔騰 4 處理器。如今,我的 2016款 MacBook Pro 的時鐘速度為 2.9 GHz。因此,差不多十年,原始處理能力都沒有太多的增加。你可以在下圖中看到處理能力的增長與時間的關係。
從上面的圖表可以看出,單執行緒的效能和處理器的頻率在近十年幾乎保持穩定。如果你認為新增更多的電晶體是一種解決問題的方法,那你就錯了。這是因為在微觀尺度上,量子特性開始顯現(例如:量子隧道穿越),放更多的電晶體代價也會越多(
所以,針對上述問題的解決方案如下:
- 廠商開始向處理器新增越來越多的核心。如今,我們已經有四核和八核的 CPU 可用。
- 我們還引入了超執行緒技術。
- 為處理器新增更多的快取以提升效能。
但是,以上方案也有它們自身的限制。我們無法向處理器新增更多的快取以提升效能,因為快取具有物理限制:快取越大,速度越慢。新增更多的核心到處理器也有它的成本。而且,這也無法無限擴充套件。這些多核處理器能同時執行多個執行緒,同時也能帶來併發能力。我們稍後會討論它。
因此,如果我們不能依賴於硬體的改進,唯一的出路就是找到一個高效的軟體來提升效能,但遺憾的是,現代程式語言都不是那麼高效。
“現代處理器就像一輛有氮氧加速系統的直線競速賽車,它們在直線競速賽中表現優異。不幸的是,現代程式語言卻像蒙特卡羅賽道,它們有大量的彎道。” - David Ungar
Go 有 goroutine!!
如上所述,硬體提供商正在向處理器新增更多的核心以提升效能。所有的資料中心都在這些處理器上執行,我們應該期待在未來幾年核心數量的增長。更重要的是,如今的應用程式都是使用多個微服務來維持資料庫的連線、訊息佇列和快取的維護。因此,我們開發的軟體和程式語言可以更容易的支援併發,並且它們應該隨著核心數量的增長而可擴充套件。
但是大多數現代程式語言(如 Java、Python 等)都來自於 90 年代的單執行緒環境。這些語言大多數都支援多執行緒。但真正的問題是併發執行,執行緒鎖、競爭條件和死鎖。這些問題都使得很難在這些語言上建立一個多執行緒的應用程式。
例如,在 Java 中建立新的執行緒會消耗大量記憶體。因為每一個執行緒都會消耗大約 1 MB 大小的堆記憶體,如果你執行上千個執行緒,他們會對堆造成巨大的壓力,最終會由於記憶體不足而宕機。此外,你想要在兩個或者多個執行緒之間通訊也是非常困難的。
另一方面,Go 於 2009 年釋出,那時多核處理器已經上市了。這也是為什麼 Go 是在考慮併發的基礎上構建的。Go 用 goroutine 來替代執行緒,它們從堆中消耗了大約 2 KB 的記憶體。因此你可以隨時啟動上百萬個 goroutine。
其他的好處:
- Goroutine 具有可增長的分段堆疊,這意味著它只會在需要的時候才會使用更多的記憶體。
- Goroutine 比執行緒啟動的更快。
- Goroutine 帶有內建原語,可以在它們(通道)之間安全的進行通訊。
- Goroutine 允許你在共享資料結構時避免使用互斥鎖。
- 此外,goroutine 和系統執行緒沒有 1:1 的對映。單個 goroutine 能在多個執行緒上執行。Goroutine 也能被複用到少量的系統執行緒上。
你能在 Rob Pike 的優秀演講併發不是並行中獲取更深刻理解。
以上這些點,能使 Go 能像 Java、C 或者 C++ 一樣擁有強大的併發處理能力,同時在保證併發執行程式碼嚴謹性的基礎上,像 Erlang 一樣優美。
Go 直接在底層硬體上執行
與其他現代高階語言(如 Java/Python)相比,使用 C、C++ 的最大好處就是它的效能,因為 C/C++ 是編譯型語言而不是解釋型語言。
處理器能理解二進位制檔案。通常來說,當你編譯一個用 Java 或者其他基於 JVM 的語言構建的應用程式,它將人類可讀的程式碼編譯為位元組程式碼,這可以被 JVM 或者在底層作業系統之上執行的其他虛擬機器器所理解。當執行的時候,虛擬機器器解釋這些位元組碼並且將他們轉化為處理器能理解的二進位制檔案。
而另一個方面,C/C++ 不會在 VM 上執行,並且從執行週期中刪除(編譯為位元組程式碼)這一步提高效能。它直接將人類可讀的程式碼編譯為二進位制檔案。
但是,在這些語言中釋放和分配變數是一件極其痛苦的事情。雖然大部分程式語言都使用垃圾回收器或者引用計數的演演算法來處理物件的分配和移除。
Go 做到了兩全其美,Go 像一些低階別的語言(如: C/C++ )一樣是一門編譯型語言,這意味著它的效能幾乎接近於低階別語言,它還用垃圾回收來分配和刪除物件。因此,不再需要 malloc() 和 free() 宣告瞭!!!這太酷了!!!
用 Go 編寫的程式碼易於維護
我告訴你一件事,Go 沒有像其他語言一樣瘋狂於程式設計語法,它的語法非常整潔。
Go 的的設計者在谷歌建立這門語言的時候就考慮到了這一點,由於谷歌擁有非常強大的程式碼庫,成千上萬的開發者都工作在相同的程式碼庫上,程式碼應該易於其他開發者理解,一段程式碼應該對另一段程式碼有最小的影響。這些都會使得程式碼易於維護,易於修改。
Go 有意的忽視了許多現代面嚮物件語言的一些特性。
- 沒有類。 所有程式碼都僅用 package 分開,Go 只有結構體而不是類。
- 不支援繼承。 這將使得程式碼易於修改。在其他語言中,如: Java/Python,如果類 ABC 繼承類 XYZ 並且你在類 XYZ 中做了一些改動,那麼這可能會在繼承類 XYZ 的其他類中產生一些副作用。通過移除繼承,Go 也使得理解程式碼變得很容易 (因為當你在看一段程式碼時不需要同時檢視父類)。
- 沒有構造方法。
- 沒有註解。
- 沒有泛型。
- 沒有異常。
以上這些改變使得 Go 與其他語言截然不同,這使得用 Go 程式設計與其他語言很不一樣。你可能不喜歡以上的一些觀點。但是,並不是說沒有上述這些特性,你就無法對你的應用程式編碼。你要做的就是多寫幾行程式碼,但從積極的一面,它將使你的程式碼更加清晰,為程式碼新增更多的清晰度。
如上圖所示,Go 幾乎與 C/C++ 一樣高效,同時像 Ruby、Python 以及其他一些語言一樣保持程式碼語法的簡潔,對於人類和處理器來說,這是一個雙贏的局面!!!
與 Swift 等這些新的語言不一樣,Go 的語法非常穩定。自從 2012 年首次公開發布 1.0 版本以來,它保持不變並且向後相容。
Go 由谷歌背書
- 我知道這不是一個直接的技術優勢,但 Go 是由谷歌設計並支援的,谷歌擁有世界上最大的雲基礎設施之一,並且規模龐大。谷歌設計 Go 以解決可擴充套件性和有效性問題。這些是建立我們自己的伺服器時都會遇到的問題。
- Go 更多的也是被一些大公司所使用,如 Adobe、BBC、IBM,因特爾甚至是 Medium。(來源:github.com/golang/go/w…)
結論
- 儘管 Go 與其他面向物件的語言非常不同,但他同樣產生了巨大的影響。Go 提供了像 C/C++ 一樣的高效能,像 Java 一樣高效的併發處理以及像 Python/Perl 一樣的編碼樂趣。
- 如果你沒有任何學習 Go 的計劃,我將仍然會說硬體的限制會給我們帶來壓力,軟體開發者應該寫超高效的程式碼。開發者應該理解硬體並相應的優化他們的程式。優化的軟體能執行在更廉價或者更慢的機器上(例如物聯網裝置),並且整體上對終端使用者體驗有更好的影響。
~如果你喜歡這篇文章,點選下方的?以便於更多的人看到它!此外,你也可以在 Medium 或者我的部落格關注我,以便於你及時獲取 Go 的更新的文章!!~
參考文獻
- GoLang 或者開發者的未來 來自於 Edoardo Paolo Scalafiotti
- 用 Go 編寫下一代伺服器
- 併發不是並行 by Rob Pike
- 為什麼是 Go?
如果發現譯文存在錯誤或其他需要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可獲得相應獎勵積分。文章開頭的 本文永久連結 即為本文在 GitHub 上的 MarkDown 連結。
掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 Android、iOS、前端、後端、區塊鏈、產品、設計、人工智慧等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃、官方微博、知乎專欄。