Rust vs. Go:為什麼強強聯合會更好

bigwhite-github發表於2021-03-17

本文翻譯自喬納森·特納(Jonathan Turner)和史蒂夫·弗朗西亞(Steve Francia)的文章《Rust vs. Go: Why They’re Better Together》

  • 史蒂夫·弗朗西亞(Steve Francia):在過去的 25 年裡,Steve Francia 建立了一些最具創新性和成功的技術和公司,這些技術和公司已經成為雲端計算的基礎,被全世界的企業和開發者所接受。他目前是谷歌 Go 程式語言的產品和戰略負責人。他是Hugo、Cobra、Viper、spf13-vim 和許多其他開源專案的建立者,擁有領導世界上最大的五個開源專案的獨特榮譽。

  • 喬納森 - 特納(Jonathan Turner)在開源領域工作了 20 多年,從小型專案到大型專案,包括幫助微軟向開源轉型。他是建立 TypeScript 團隊的一員,並作為專案經理和設計團隊的負責人幫助其成長。他還作為 Rust 社群成員和 Mozilla Rust 團隊的一員參與 Rust 的工作,包括共同設計 Rust 的錯誤資訊和 IDE 支援。

雖然其他人可能認為RustGo是競爭性的程式語言,但 Rust 和 Go 團隊卻都不這麼認為。恰恰相反,我們的團隊非常尊重其他團隊正在做的事情,並認為這兩種程式語言是相輔相成的,有著共同的願景,即在整個行業內實現軟體開發狀態的現代化。

在本文中,我們將討論 Rust 和 Go 的優缺點、它們如何相互補充和支援以及我們對每種語言的最佳使用時機的建議。

一些公司正在發掘採用這兩種語言的價值以及它們的互補價值。為了從我們的觀點轉向使用者的實際體驗,我們採訪了三家這樣的公司,DropboxFastlyCloudflare,講述了他們共同使用 Go 和 Rust 的經驗。他們的經驗之談將被引用並貫穿本文,為大家提供更進一步的觀點。

1. 語言比較

程式語言 Go Rust
建立時間 2009 2010
建立於 谷歌 Mozilla
知名專案 Kubernetes,Docker,Github CLI,Hugo,Caddy,Drone,Ethereum,Syncthing,Terraform Firefox, ripgrep, alacritty, deno, Habitat
典型用途 APIs, Web Apps, CLI apps, DevOps, Networking, Data Processing, cloud apps IoT, processing engines, security-sensitive apps, system components, cloud apps
開發者採用 8.8%(第 12 名) 5.1%(第 19 名)
開發者最愛 62.3%(第 5 名) 86.1%(第 1 名)
開發最想要 17.9%(第 3 名) 14.6%(第 5 名)

2. 相似之處

Go 和 Rust 有很多共同點。兩者都是現代軟體語言,都是出於為影響軟體開發的問題提供一個安全和可擴充套件的解決方案的需要而誕生的。兩者都是為了應對建立者在行業內現有語言中遇到的缺點而建立的,尤其是開發者生產力、可擴充套件性、安全性和併發性方面的缺點。

當今流行的大多數語言都是 30 多年前設計的。當這些語言被設計出來的時候,與今天有五個關鍵的區別:

  • 摩爾定律被認為是永恆不變的。
  • 大多數軟體專案都是由小團隊編寫的,並且經常一個人單幹。
  • 大多數軟體有相對較少的依賴性,大多數是專有的。
  • 安全性是次要的考慮因素......或者根本不是考慮因素。
  • 軟體通常是為單一平臺編寫的。

相比之下,Rust 和 Go 都是為今天的世界而寫的,並都採取了相似的方法來設計一種適合今天開發需求的語言。

1) 效能和併發

Go 和 Rust 都是專注於生產高效程式碼的編譯語言。它們還可以方便地使用當今機器的多個處理器,使它們成為編寫高效並行程式碼的理想語言。

  • "使用 Go 使得 MercadoLibre 公司將他們用於這項服務的伺服器數量減少到原來的八分之一(從 32 臺伺服器減少到 4 臺),另外,每臺伺服器可以用更少的功率執行(原來是 4 個 CPU 核,現在減少到 2 個 CPU 核)。有了 Go,該公司省去了 88% 的伺服器,並將剩餘伺服器上的 CPU 削減了一半 -- 產生了巨大的成本節約。"--"MercadoLibre 與 Go 一起成長"

  • "在我們嚴格管理的環境中,在我們執行 Go 程式碼的環境中,我們看到 CPU 減少了大約百分之十 [與 C++ 相比],程式碼更乾淨,更可維護。" - Bala Natarajan,Paypal

  • "在 AWS,我們也很喜歡 Rust,因為它能幫助 AWS 編寫高效能、安全的基礎設施級網路和其他系統軟體。亞馬遜第一個用 Rust 構建的重要產品 Firecracker 於 2018 年公開發布,它提供了開源虛擬化技術,為 AWS Lambda 和其他無伺服器產品提供動力。但我們也使用 Rust 來提供亞馬遜簡單儲存服務(Amazon S3)、亞馬遜彈性計算雲(Amazon EC2)、Amazon CloudFront、Amazon Route 53 等服務。最近,我們推出了基於 Linux 的容器作業系統 Bottlerocket,它是用 Rust 編寫的。" - Matt Asay,亞馬遜網路服務

  • 我們"看到我們的速度非凡地提高了 1200-1500%! 我們從實現了較少解析規則的 Scala 的模式下的 300-450ms,到實現了更多解析模式的 Rust 模式下的 25-30ms!" - Josh Hannaford,IBM

2) 團隊可擴充套件 ---- 可審查

今天的軟體開發是由團隊建立的,這些團隊不斷成長和擴大,經常使用原始碼控制以分散式的方式進行協作。Go 和 Rust 都是針對團隊的工作方式而設計的,通過消除不必要的擔憂,如格式 (比如 go 的 gofmt)、安全和複雜的組織,來改善程式碼審查。這兩種語言都需要相對較少的上下文來理解程式碼的工作,使審查人員能夠更快速地使用其他人編寫的程式碼,並審查團隊成員的程式碼和你團隊以外的開源開發人員貢獻的程式碼。

  • “我早期的職業生涯有 Java 和 Ruby 的背景,構建 Go 和 Rust 程式碼對我來說就像卸下了無法承受的重擔。當我在 Google 時,遇到用 Go 編寫的服務讓我很欣慰,因為我知道它易於構建和執行。Rust 的情況也是如此,儘管我只是在更小的工作範圍內使用了它。我希望無限可配置的構建系統的日子已經過去了,而語言都有自己的專用構建工具,開箱即用。"-- Sam Rose,CV 合夥人

  • "用 Go 寫服務的時候,我往往會鬆一口氣,因為與動態語言相比,Go 的靜態型別系統非常簡單,易於推理,併發性是一等公民,Go 的標準庫既無比精緻強大,又切中要害。安裝一個標準的 Go,再使用一個 grpc 庫和一個資料庫聯結器,你在伺服器端幾乎不需要其他的東西,每個工程師都能看懂程式碼,看懂庫。在用 Rust 編寫模組時,Dropbox 工程師在 2019 年 Async-await 穩定下來之前,感受到了 Rust 在伺服器端的成長之痛,但從那時起,crate(譯註:Rust 中的概念) 正在趨向於使用它,我們得到了 Async 模式並從併發中受益。" - Daniel Reiter Horn,Dropbox

3) 開放原始碼意識

今天一般軟體專案所使用的依賴關係數量是驚人的。長達幾十年的軟體重用目標在現代開發中已經實現,今天的軟體可能是複用了 100 多個專案而構建的。為此,開發人員使用軟體倉庫,這越來越成為軟體開發的主旋律,並在越來越廣泛的領域應用。開發者所包含的每一個軟體包,又有自己的依賴關係。為今天的程式設計環境而設計出的程式語言需要毫不費力地處理這種複雜性。

Go 和 Rust 都有包管理系統,允許開發人員列出一個簡單的清單,列出他們想要構建的包,語言工具就會自動為他們獲取和維護這些包,這樣開發人員就可以把更多的精力放在自己的程式碼上,而不是放在對其他包的管理上。

4) 安全性

Go 和 Rust 都很好地解決了當今應用的安全問題,保證了用這些語言構建的程式碼在執行時不會讓使用者暴露在各種經典的安全漏洞中,比如緩衝區溢位、use-after-free(記憶體釋放後還使用) 等。通過消除這些顧慮,開發者可以專注於手頭的問題,並在預設情況下構建更安全的應用程式。

  • “Rust 編譯器在解決您遇到的錯誤時確實能助您一臂之力。這樣一來,您就可以專注於自己的業務目標,而不必尋找錯誤或解密隱祕訊息。” -Josh Hannaford,IBM

  • 簡而言之,Rust 的靈活性,安全性和安全性帶給我們的益處超過了必須遵循嚴格的 lifetime,borrow(rust 中的概念) 和其他編譯器規則甚至缺乏垃圾收集器所帶來的任何不便。這些功能是雲軟體專案中非常需要的功能,將有助於避免其中常見的許多錯誤。” —微軟高階泰勒·托馬斯(Taylor Thomas)

  • "Go 是強靜態型別化的,沒有隱式轉換,但語法開銷還是小得驚人。這是通過賦值中簡單的型別推理與非型別化的數值常量一起實現的。這使得 Go 比 Java(有隱式轉換)具有更強的型別安全性,但程式碼讀起來更像 Python(有非型別變數)。" - Stefan Nilsson,電腦科學教授

  • "當我們在 Dropbox 構建用於儲存塊資料的 Brotli 壓縮庫時,我們將自己限制在 Rust 的安全子集上,而且,也限制在核心庫(no-stdlib)上,分配器指定為通用。這樣使用 Rust 的子集,使得在客戶端從 Rust 呼叫 Rust-Brotli 庫,以及在伺服器上使用 Python 和 Go 的 C FFI 變得非常容易。這種編譯模式也提供了大量的安全保障。經過一些調整,Rust Brotli 的實現儘管是 100% 安全的、經過陣列邊界檢查的程式碼,但仍然比 C 語言中相應的原生 Brotli 程式碼快。" - Daniel Reiter Horn,Dropbox

5) 真正的可移植性

在 Go 和 Rust 中,寫一個軟體,在許多不同的作業系統和架構上執行是很容易的。"一次編寫,隨處編譯"。此外,Go 和 Rust 都原生支援交叉編譯,消除了舊編譯語言常見的"build farm"的需要。

  • "Go 在生產優化方面擁有很好的特質,比如擁有較小的記憶體佔用,這支援其在大型專案中被用於構建模組,以及開箱即用,易於交叉編譯到其他架構。由於 Go 程式碼被編譯成單一的靜態二進位制,我們可以輕鬆將其容器化,並且通過擴充套件,我們可以很輕鬆地將 Go 部署到任何高可用環境(如 Kubernetes)中。" - Dewet Diener,Curve

  • "當你看一個基於雲的基礎設施時,通常你會使用類似 Docker 容器這樣的東西來部署你的工作負載。通過在 Go 中構建的靜態二進位制,你可以擁有一個 10、11、12 兆位元組的 Docker 檔案,而不是帶來整個 Node.js 生態系統,或像 Python 或 Java 那樣動輒數百兆位元組大小的 Docker 映象檔案。所以,交付那個微小的二進位制檔案是很神奇的。" - Brian Ketelsen,微軟

  • "有了 Rust,我們將擁有一個高效能和可移植的平臺,我們可以輕鬆地在 Mac、iOS、Linux、Android 和 Windows 上執行。" - Matt Ronge,Astropad

3. 差異

在設計中,總是要做出一些取捨。雖然 Go 和 Rust 大約在同一時間出現,目標相似,但由於他們決策時選擇了不同的取捨,使得這兩種語言在關鍵的方面有所區別。

1) 效能方面

Go 開箱即有出色的效能。在設計上,幾乎沒有預留任何旋鈕或開關可以讓你從 Go 中榨取更多的效能。Rust 的設計是為了讓您能夠從程式碼中榨取每一滴效能;在這方面,您確實無法找到比 Rust 更快的語言。然而,Rust 的效能提升是以額外的複雜性為代價的。

  • "值得注意的是,在編寫 Rust 版本時,我們只在優化方面投入了非常基本的思考。即使只做了基本的優化,Rust 的效能也能超過超手工調整的 Go 版本。這極大地證明了用 Rust 編寫高效的程式是多麼容易,相比之下,我們不得不對 Go 進行深挖。" - Jesse Howarth,Discord

  • "Dropbox 工程師通過將行對行的 Python 程式碼移植到 Go 中,往往可以看到 5 倍的效能提升和延遲下降,與 Python 相比,記憶體使用率往往會大幅下降,因為沒有 GIL,程式數可能會減少。然而,當我們的記憶體受限時,比如在桌面客戶端軟體或某些伺服器程式中,我們會轉而使用 Rust,因為 Rust 中的手動記憶體管理效率大大高於 Go GC。" - Daniel Reiter Horn,Dropbox

2) 適應性/互動性

Go 快速迭代的優勢讓開發人員可以快速嘗試各種想法,並磨合出能解決手頭任務的工作程式碼。通常情況下,這就足夠了,可以讓開發者騰出手來處理其他任務。另一方面,與 Go 相比,Rust 的編譯時間更長,導致迭代時間更慢。這就導致了 Go 在一些場景中能更好地工作,因為更快的週轉時間能讓開發人員適應不斷變化的需求,而 Rust 則在一些場景中茁壯成長,因為在這些場景中,可以給予更多的時間來做出更精緻、更高效能的實現。

  • "Go 型別系統的天才之處在於呼叫者可以定義 Interface,允許庫返回僅需滿足小介面但卻支援擴充套件的結構。Rust 型別系統的天才設計在於匹配語法與 Result<>的結合,你可以靜態地確定每一種可能性都會被處理,永遠不必發明空值來滿足未使用的返回引數。" - Daniel Reiter Horn,Dropbox

  • "(我) 如果你的用例離客戶更近,更容易受到需求變化的影響,那麼用 Go 就會好很多,因為持續重構的成本要便宜很多。這就是你能多快地表達新的需求並嘗試它們。" - Peter Bourgon,Fastly

3) 可學性

簡單來說,真的沒有比 Go 更 “平易近人” 的語言了。有很多團隊能夠在幾周內採用 Go 並將 Go 服務/應用投入生產的故事。此外,Go 在語言中是比較獨特的,它的語言設計和實踐在它 10 多年的生命中是相當一致的。所以,投入到學習 Go 上的時間可以保持很長一段時間的價值。相比之下,Rust 由於其複雜性,被認為是一門難學的語言。一般來說,學習 Rust 需要幾個月的時間才能感覺到自如,但這種額外的複雜性也帶來了精確的控制和效能的提高。

  • "當時,沒有一個團隊成員知道 Go,但在一個月內,每個人都在用 Go 寫作"--Jaime Garcia,Capital One

  • "Go 與其他程式語言不同的地方在於認知負擔。你可以用更少的程式碼做更多的事情,這使得你更容易推理和理解你最終編寫的程式碼。大多數 Go 程式碼最終看起來都很相似,所以,即使你在使用一個全新的程式碼庫,你也可以很快上手並執行。" - Glen Balliet 美國運通忠誠度平臺工程總監 美國運通使用 Go 進行支付和獎勵

  • "然而,與其他程式語言不同,Go 是為了最大限度地提高使用者效率而建立的。因此,具有 Java 或 PHP 背景的開發人員和工程師可以在幾周內獲得使用 Go 的高階技能和培訓 -- 根據我們的經驗,他們中的許多人最終都喜歡上了 Go。" - Dewet Diener,Curve

4) 精確控制

也許 Rust 最大的優勢之一就是開發者對如何管理記憶體、如何使用機器的可用資源、如何優化程式碼以及如何製作問題解決方案的控制。與 Go 相比,這並不是沒有很大的複雜度成本,因為 Go 的設計並不是為了這種精確的製作,而是為了更快的探索時間和更快的週轉時間。

  • >"隨著我們對 Rust 經驗的增長,它在另外兩個軸上顯示出了優勢:作為一種具有強大記憶體安全性的語言,它是邊緣處理的好選擇;作為一種具有巨大熱情的語言,它成為了重寫元件的流行語言。" - John Graham-Cumming,Cloudflare。

3. 總結/主要收穫

Go 的簡單性、效能和開發人員的生產力使 Go 成為建立面向使用者的應用程式和服務的理想語言。快速的迭代讓團隊能夠快速地作出反應以滿足使用者不斷變化的需求,讓團隊有辦法將精力集中在靈活性上。

Rust 更精細的控制允許更多的精確性,使得 Rust 成為低階操作的理想語言,這些低階操作不太可能發生變化,並且會從比 Go 略微提高的效能中受益,特別是在非常大的規模部署時。

Rust 的優勢在最接近 “金屬”(指底層機器) 的地方。Go 的優勢是在離使用者更近的地方最有利。這並不是說兩者都不能在對方的空間裡工作,但這樣做會增加摩擦。當你的需求從靈活性轉變為效率時,用 Rust 重寫庫的理由就更充分了。

雖然 Go 和 Rust 的設計有很大的不同,但它們的設計發揮了相容的優勢,而且 -- 當一起使用時 -- 既可以有很大的靈活性,又可以有很好的效能。

4. 我們的建議

對於大多數公司和使用者來說,Go 是正確的預設選擇。它的效能很強,Go 很容易採用,而且 Go 的高度模組化特性使它特別適合需求不斷變化或發展的情況。

隨著你的產品逐漸成熟,需求趨於穩定,可能會有機會從效能的邊際增長中獲得巨大的勝利。在這些情況下,使用 Rust 來最大限度地提高效能可能很值得你進行初始投資。


Go 技術專欄 “改善 Go 語⾔程式設計質量的 50 個有效實踐” 正在慕課網火熱熱銷中!本專欄主要滿足廣大 gopher 關於 Go 語言進階的需求,圍繞如何寫出地道且高質量 Go 程式碼給出 50 條有效實踐建議,上線後收到一致好評!歡迎大家訂閱!目前該技術專欄正在新春促銷!關注我的個人公眾號 “iamtonybai”,傳送 “go 專欄活動” 即可獲取專欄專屬優惠碼,可在訂閱專欄時抵扣 20 元哦 (2021.2 月末前有效)。

Gopher Daily(Gopher 每日新聞) 歸檔倉庫 - https://github.com/bigwhite/gopherdaily

我的聯絡方式:

更多原創文章乾貨分享,請關注公眾號
  • Rust vs. Go:為什麼強強聯合會更好
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章