【GoCN譯文視點】何時使用 Rust, 何時使用 Go
直截了當(dāng)?shù)恼f, Go 和 Rust 之間有明顯的區(qū)別。Go 更加注重構(gòu)建可擴展的 Web API 和微服務(wù),尤其是有 goroutine 的助力。雖然 Rust 作為后者也可以做這些事情,但是開發(fā)體驗要差許多。

Rust 非常適合處理大量數(shù)據(jù)和其他 CPU 密集型操作,例如執(zhí)行算法。這是 Rust 相比于 Go 的最大優(yōu)勢。要求高性能的項目通常更適合 Rust 。
在本教程中,我們將對 Go 和 Rust 進行比對,評估各自的并發(fā)性,內(nèi)存管理和開發(fā)體驗。我們還會對這些事物做出綜述,來幫助你快速為項目做技術(shù)選型。
如果這吸引了你,我們開始深入講解!
性能
Go 最初是由 Google 的工程師設(shè)計的,于 2009 年公布。它作為 C++ 的替代方案而產(chǎn)生,易于學(xué)習(xí)和編碼,并且經(jīng)過優(yōu)化可在多核 CPU 上運行。
自那之后,Go 語言變得非常適合希望利用語言內(nèi)置并發(fā)性的開發(fā)者。該語言提供的 goroutine 可以使你像子進程一樣運行函數(shù)。
Go 的一大優(yōu)勢是您可以輕松使用 goroutine。只需將 go 關(guān)鍵字寫到到函數(shù)前即可使其作為子進程運行。Go 的并發(fā)模型使您可以在多個 CPU 內(nèi)核之間平衡工作負載,使其成為一種非常高效的語言。
package main
import (
"fmt"
"time"
)
func f(from string) {
for i := 0; i < 3; i++ {
fmt.Println(from, ":", i)
}
}
func main() {
f("direct")
go f("goroutine")
time.Sleep(time.Second)
fmt.Println("done")
}
盡管有多核 CPU 支持,Rust 仍然可以跑贏 Go。Rust 在執(zhí)行算法和資源密集型操作方面效率更高?;鶞蕼y試通過各種算法將 Rust 和 Go 做比較,例如二叉樹。對于所有測試算法,Rust 至少快 30%;在二叉樹計算的情況下,最高可達 1,000%。Bitbucket的一項研究表明,Rust與C++的性能相似。

(來源: 基準測試)
并發(fā)性
如上所述,Go 支持并發(fā)。例如,假設(shè)您正在運行一個處理 API 請求的網(wǎng)絡(luò)服務(wù)器。您可以使用 Go 的 goroutine 將每個請求作為子進程運行,將任務(wù)分布到所有可用的 CPU 核心來最大化效率。
Goroutine 是 Go 內(nèi)置函數(shù)的一部分,而 Rust 僅支持使用 async/await 來實現(xiàn)并發(fā)。因此,當(dāng)涉及到并發(fā)時,Go 的開發(fā)體驗更好。但是,Rust 在內(nèi)存安全性方面要好得多。
這是一個簡化的 Rust 線程示例:
use std::thread;
use std::time::Duration;
fn main() {
// 1. create a new thread
for i in 1..10 {
thread::spawn(|| {
println!("thread: number {}!", i);
thread::sleep(Duration::from_millis(100));
});
}
println!("hi from the main thread!");
}
并發(fā)一直是開發(fā)人員的棘手問題。在不損害開發(fā)體驗的前提下,確保內(nèi)存安全的并發(fā)并不是一件容易的事。但是,正是這種對安全的極端關(guān)注導(dǎo)致了可證明是正確的并發(fā)模型的產(chǎn)生。Rust 嘗試使用所有權(quán)概念來防止未經(jīng)授權(quán)的資源訪問,以防止出現(xiàn)內(nèi)存安全錯誤。
Rust提供了四種不同的并發(fā)范式,以幫助您避免常見的內(nèi)存安全陷阱。我們將仔細研究兩個常見的范例:通道(Channel)和 鎖(Lock)。
通道
通道有助于將消息從一個線程傳輸?shù)搅硪粋€線程。雖然 Go 也存在這種概念,但 Rust 允許您將指針從一個線程轉(zhuǎn)移到另一個線程,以避免資源競爭。通過傳遞指針,Rust 可以為通道強制執(zhí)行線程隔離。同樣,Rust 的并發(fā)模型也表現(xiàn)出對內(nèi)存安全的“癡迷”。
鎖
僅在持有鎖時才能訪問數(shù)據(jù)。Rust 依賴于鎖定數(shù)據(jù)的原則而不是 cod(condition機制),而 cod 經(jīng)常在諸如 Java 之類的編程語言中找到。
有關(guān)所有權(quán)和所有并發(fā)范例的更多詳細信息,請查看 “Fearless Concurrency with Rust”(無畏并發(fā))。
內(nèi)存安全
早期的所有權(quán)概念是 Rust 的主要賣點之一。Rust 具有類型安全性,這一點對于用于將內(nèi)存安全并發(fā)提升到一個新的水平很重要
根據(jù) Bitbucket 博客的說法,“ Rust 非常嚴格且繁瑣的編譯器會檢查您使用的每個變量以及您引用的每個內(nèi)存地址。它避免了可能的數(shù)據(jù)競爭情況,并通知您關(guān)于未定義行為的信息?!?/p>
這意味著,由于 Rust 對內(nèi)存安全性的極度癡迷,您將不會出現(xiàn)緩沖區(qū)溢出或競爭條件。但是,這也有其缺點。例如,您在編寫代碼時必須非常了解內(nèi)存分配原則。始終保持內(nèi)存安全編程并不容易。
開發(fā)體驗
首先,讓我們看一下這兩種語言的學(xué)習(xí)曲線。Go 的設(shè)計考慮了簡單性。開發(fā)人員經(jīng)常將其稱為“無聊的”語言,也就是說,其有限的內(nèi)置功能使 Go 易于使用。
此外,Go 作為一種 C++ 的簡單替代方法,隱藏了諸如內(nèi)存安全性和內(nèi)存分配之類的問題。Rust 走了另一條路,強迫您考慮諸如內(nèi)存安全性的概念。所有權(quán)的概念和可以傳遞指針的能力使 Rust 變得不那么吸引人學(xué)習(xí)。當(dāng)您不斷考慮內(nèi)存安全性時,您的工作效率就會降低,并且您的代碼注定會變得更加復(fù)雜。
與 Go 相比,Rust 的學(xué)習(xí)曲線非常陡峭。值得一提的是,與 Python 和 JavaScript 等動態(tài)語言相比,Go 的學(xué)習(xí)曲線更為陡峭。
什么時候使用 Go
Go 在各種場景中都能很好地工作,使其成為創(chuàng)建 Web API 的 Node.js 的絕佳替代品。正如 Loris Cro 指出的那樣,“ Go 的并發(fā)模型非常適合必須處理多個獨立請求的服務(wù)器端應(yīng)用程序”。這正是 Go 提供 goroutine 的原因。
除此之外,Go 內(nèi)置了對 HTTP Web 協(xié)議的支持。您可以使用內(nèi)置的 HTTP 支持快速實現(xiàn)一個小型 API,并將其作為微服務(wù)運行。因此,Go 非常適合微服務(wù)架構(gòu),可滿足 API 開發(fā)人員的需求。
簡而言之,如果您重視開發(fā)速度并且更喜歡簡單的語法而不是極致的性能,那么 Go 是一個很好的選擇。最重要的是,Go 提供了更好的代碼可讀性,更符合大型開發(fā)團隊的準則。
這時候使用 Go:
你關(guān)注簡潔性和可讀性 你需要簡單的語法來快速編寫代碼 你想要使用一種更加靈活的語言來做 web 開發(fā)
什么時候使用 Rust
當(dāng)性能至關(guān)重要時,例如處理大量數(shù)據(jù)時,Rust 是一個不錯的選擇。此外,Rust 在線程行為和資源跨線程共享方面為您提供了細粒度控制的可能。另一方面,Rust 具有陡峭的學(xué)習(xí)曲線,并且由于內(nèi)存安全性的額外復(fù)雜性而減慢了開發(fā)速度。這不一定是不利的。Rust 還讓編譯器檢查每個數(shù)據(jù)指針,來保證您不會遇到內(nèi)存安全錯誤。對于復(fù)雜的系統(tǒng),此保證會派上用場。
這時候使用 Rust:
你關(guān)注性能 你需要對于線程的細粒度控制 你認為內(nèi)存安全性比簡潔性更重要
Go vs. Rust: 我的肺腑之言
讓我們首先強調(diào)相似之處。Go 和 Rust 都是開源的,旨在支持微服務(wù)架構(gòu)和并行計算環(huán)境。兩者都通過并發(fā)優(yōu)化了可用 CPU 內(nèi)核的利用率。
說到底,哪種語言是最好的?
有很多方法可以解決這個問題。我建議您考慮要構(gòu)建的應(yīng)用程序種類。Go 可以很好地利用內(nèi)置的并發(fā)特性來創(chuàng)建微服務(wù)架構(gòu)下的 Web 應(yīng)用程序和 API。
您也可以使用 Rust 來開發(fā) Web API,但這不是在設(shè)計時考慮到的。Rust 專注于內(nèi)存安全性會增加復(fù)雜性和開發(fā)時間,尤其是對于相當(dāng)簡單的 Web API 而言。但是,對代碼的大量控制使您可以編寫更優(yōu)化,內(nèi)存效率更高且性能更高的代碼。
簡而言之,Go 與 Rust 的爭論實際上是一個簡單與安全的問題。
