在這篇文章中,我將嘗試比較 GoLang、Zig 和 Rust。以及為什麼 Rust 贏得了這次比較(對我來說)。
我用 GoLang、Zig 和 Rust 寫了 3 個專案。這些專案足夠大,可以很好地了解語言基礎知識、缺點以及語言、框架或生態系統是否有問題。
提示:請隨意跳到 TLDR 部分以獲得該死的答案。
幾個月前,我開始建立開發人員工具,最初是使用 GoLang。
第一個是基本的資料庫管理和遷移實用程式 ( dbdaddy ),我真的很喜歡使用 GoLang。
儘管這是我第一次嘗試用 GoLang 建置比 Advent Of Code 和 10 億行挑戰問題更嚴重的東西,但令我驚訝的是我只花了不到一周的時間就精通了它。
一直以來,我都在和 Zig 一起玩(沒什麼太嚴重的)。我聽說 Redis 將其許可證更改為“技術上非開源”許可證。
我心想:在zig中建立一個新的開源redis有多難?
快轉兩個月後:該死。
「 GbCache 」背後的基本思想是基於 LRU 的記憶體緩存,但實際的事實來源是與諸如引起的特定鍵/值更改的通知以及分配給鍵的 TTL 等功能一起保存在磁碟上。
Zig 的明確性令人印象深刻,這使得它變得更加簡單且易於使用。
我從「如果明天要採用 HyperScale™,它能處理負載嗎?」的角度開始使用 GbCache。
這種觀點促使我排除了 GoLang,因為如果我無法極其確定地推理記憶體分配,我將無法完全控制速度。
從這個角度做事是一次非常好的學習經歷,因為突然你開始看到程式中可能崩潰、耗盡記憶體或可能成為瓶頸的所有點——程式碼中的熱路徑。
由於 Zig 的明確性,我確信我在何時何地分配記憶體。
但是... Zig 歸根結底並不是一種記憶體安全的語言,而我是一個技術問題與珠穆朗瑪峰一樣大的人。
進入生鏽狀態
在過去的兩年裡,我曾 3 次嘗試並憤怒地退出 Rust。來自 JavaScript 背景,我們的 macbook m69 maxes 中有大量 GB 內存,我從來沒有真正理解為什麼 Rust 有這些規則,並且從炒作的角度來看待它可能是一個糟糕的角度。
儘管我多次憤怒地退出,Rust 仍然在我的腦海中,它奇怪的語言、令人沮喪的內存規則和令人難以置信的生命週期。
但在寫 Zig 時,我受到了一些打擊……我已經在跟踪所有這些記憶規則和生命週期,但作為一種精神開銷。
我開始注意到 Zig 程式碼中的模式和樣板,試圖做 Rust 已經在做的事情。
在為SFS (SFW 名稱 - “簡單檔案儲存”)建立 CLI 用戶端時,我決定再次嘗試 Rust。
這次,在翻閱這本生鏽的書時,我開始感受到這一切的「原因」。
我喜歡 Rust 的最基本的一點是基於所有權和借用的記憶心理模型。
儘管這種擁有和引用記憶體的模型是虛構的,但它是一種方便推理的心理模型,並且在我的頭腦中產生的開銷更少。
與 C 和 Zig 這樣的語言在你的頭腦中產生的經典心理記憶模型相反。必須在腦海中追蹤各個記憶體分配及其生命週期嗎?不,謝謝!
快(就像你的 5 個月活躍用戶會需要它一樣)
可靠的
愚蠢簡單,語言永遠不會阻礙你和你的目標
偉大的軟體包生態系統
速度極快
愚蠢簡單
速度極快
可靠的
偉大的軟體包生態系統
如果您是日常普通後端工程師並且喜歡對衝刺性能進行統計,那麼您最好的選擇可能是GoLang 。
“但我的公司不使用 GoLa——”
“離開公司,離開它,為工具使用正確的工作。離開公司。”
對我來說,GoLang 就像一場包辦婚姻,你永遠不會感到內心的急躁,但它永遠不會讓你失望,它是你生死攸關的伴侶,你可以把你的一生都押在它上面。
但我的朋友,如果您正在尋找那種快感,請繼續閱讀!
bu——但我想要那種衝動……我想要看到他們的眼睛語法時我的心爆炸……我想要感覺當我和他們在一起時我在天堂,而當我和他們在一起時我感覺我在地獄我不是...
讓我們快速看一下 Rust 中多執行緒安全的範例。
use std::thread;
fn main() {
let mut counter = Box::new(0); // 32-bit integer allocated on the heap
let mut handles = vec![];
for _ in 0..10 {
let handle = thread::spawn(|| {
*counter += 1; // trying to edit the value
});
handles.push(handle);
}
for handle in handles {
handle.join().unwrap(); // WAITING FOR ALL THE THREADS TO COMPLETE
}
println!("Result: {}", *counter);
}
我們有一個堆分配的值,並且有 10 個線程嘗試獨立修改它。
此程式碼不安全地存取counter
變數,因為所有執行緒將嘗試同時修改counter
。
在其他語言中,類似的程式碼可以愉快地編譯和執行。
如果您以前在多執行緒環境中工作過,您的第一個想法可能是使用「互斥體」來防止更新counter
變數時的競爭條件。
但由於人為錯誤,在大型程式碼庫中很容易錯過這樣的小事。
Rust 甚至不會讓這個程式編譯。
由於所有權和借用規則,編譯器將檢測到您在 for 循環的第一次迭代中的第一個線程中可變地借用counter
...到目前為止還好...第二次迭代也想並行地可變地借用counter
?不安全!引發編譯時錯誤! 。
出於變異/修改的目的而引用或“借用”其所有者的值稱為“可變借用”
src/main.rs|8 col 36-38 error| cannot borrow `*counter` as mutable more than once at a time `*counter` was mutably borrowed here in the previous iteration of the loop
在這種情況下,其他語言根本不會給你任何錯誤。檢查正確性是你的責任,Rust 會阻止這種情況發生。
像這樣遍布整個語言的結構可以幫助你避免搬起石頭砸自己的腳(經常)。
這取決於!
我真的希望有一種語言可以作為答案,即使 GoLang 非常接近這個答案,它實際上取決於您的用例,最重要的是您的團隊。
對我來說,與 Rust 合作很愉快(現在,誰知道呢…呵呵)
TigerBeetle的員工在Zig上嘗試了一次機會,他們對此感到滿意。
Primeagen 對Zig感到更滿意。
對於賈里德·薩姆納(Jarred Sumner)來說, 《Zig》很好,他在《Zig》中寫了《Bun》 。
Mitchell Hashimoto(HashiCorp 背後的人)正在Zig中寫Ghostty ,這是一個速度極快的術語——
。
。
。
等待...
原文出處:https://dev.to/kuvambhardwaj/i-tried-every-hot-programming-language-514f