In diesem Beitrag werde ich versuchen, GoLang, Zig und Rust zu vergleichen. Und warum Rust diesen Vergleich (für mich) gewinnt.
Ich habe drei meiner Projekte in GoLang, Zig und Rust geschrieben. Diese Projekte sind groß genug, um eine gute Vorstellung von den Grundlagen und Mängeln der Sprache zu bekommen und festzustellen, ob ein Problem mit der Sprache, dem Framework oder dem Ökosystem vorliegt.
TIPP: Springen Sie gerne zum TLDR-Bereich, um die verdammte Antwort zu erhalten.
Ich habe vor ein paar Monaten mit der Entwicklung von Entwicklertools begonnen, zunächst mit GoLang.
Das erste war ein einfaches Dienstprogramm zur Datenbankverwaltung und -migration (dbdaddy), und die Arbeit mit GoLang hat mir wirklich Spaß gemacht.
Obwohl dies mein allererster Versuch mit GoLang war, etwas Ernsthafteres als Advent Of Code und 1-Milliarde-Zeilen-Challenge-Probleme zu entwickeln, war ich überrascht, dass ich weniger als eine Woche brauchte, um mich darin zurechtzufinden .
Die ganze Zeit über habe ich mich nebenbei mit Zig beschäftigt (nichts allzu Ernstes). Ich habe gehört, dass Redis seine Lizenz in eine „technisch nicht Open-Source“-Lizenz geändert hat.
Und ich dachte mir: Wie schwer kann es sein, im Zickzack ein neues Open-Source-Redis zu erstellen?
Schneller Vorlauf 2 Monate später: verdammt.
Die Grundidee hinter „GbCache“ war ein LRU-basierter In-Memory-Cache, aber die eigentliche Quelle der Wahrheit sollte auf der Festplatte gespeichert werden, zusammen mit Funktionen wie Benachrichtigungen für bestimmte verursachte Schlüssel-/Wertänderungen und natürlich den Schlüsseln zugewiesenen TTLs.
Es ist beeindruckend, wie explizit Zig ist, was die Arbeit damit umso einfacher und einfacher macht.
Ich habe GbCache aus der Perspektive gestartet: „Wenn es morgen auf HyperScale™ umsteigen würde, kann es die Last bewältigen?“
Diese Perspektive veranlasste mich, GoLang auszuschließen, denn wenn ich nicht in der Lage bin, mit äußerster Sicherheit über die Speicherzuordnungen nachzudenken, habe ich keine vollständige Kontrolle über die Geschwindigkeit.
Dinge aus dieser Perspektive zu machen, ist eine wirklich tolle Lernerfahrung, denn plötzlich sieht man alle Punkte in Ihrem Programm, die explodieren, nicht mehr genügend Speicher haben oder zu einem Engpass werden könnten –die heißen Pfade in Ihrem Code.
Aufgrund der Deutlichkeit von Zig wusste ich genau, wo und wann ich Speicher zuordne.
Aber... Zig ist letztendlich KEINE speichersichere Sprache und ich bin ein Typ mit Fähigkeiten von der Größe des Everest.
Es tritt Rost ein
In den letzten 2 Jahren habe ich dreimal versucht, aus purer Wut aufzuhören. Da ich aus einem JavaScript-Hintergrund komme und in unserem MacBook M69 Max Bajillionen GB RAM haben, habe ich nie wirklich verstanden, warum Rust diese Regeln hatte, und sich auf den Hype einzulassen, war wahrscheinlich ein schlechter Blickwinkel .
Obwohl ich mehrmals vor Wut aufgehört habe, war Rust immer noch im Hinterkopf, seine seltsame Syntax, frustrierende Speicherregeln und umwerfende Lebenszeiten.
Aber beim Schreiben von Zig ist mir etwas aufgefallen... Ich habe all diese Gedächtnisregeln und Lebenszeiten bereits im Auge behalten, aber nur als mentalen Overhead.
Ich bemerkte Muster und Muster in meinem Zig-Code, die versuchten, das zu tun, was Rust bereits tut.
Beim Erstellen des CLI-Clients für SFS (SFW-Name – „Simple File Storage“) habe ich beschlossen, Rust noch einmal zu versuchen.
Dieses Mal, als ich das Rostbuch durchging, begann ich das „Warum“ des Ganzen zu spüren.
Das Grundlegendste, was ich an Rust liebe, ist das auf Eigentum und Ausleihen basierende mentale Modell der Erinnerung.
Auch wenn dieses Modell des eigenen und referenzierten Gedächtnisses imaginär ist, ist es ein praktisches mentales Modell zum Nachdenken und verursacht mir weniger Aufwand.
Im Gegensatz zum klassischen mentalen Gedächtnismodell, das Ihnen Sprachen wie C und Zig in den Sinn bringen. Muss ich individuelle Speicherzuordnungen und deren Lebensdauer in meinem Kopf verfolgen? Nein danke!
Wenn Sie ein normaler Mo-Backend-Ingenieur sind und gerne Zahlen zu seiner Sprintleistung erstellen, ist GoLang Ihre beste Wahl.
„Aber mein Unternehmen nutzt GoLa nicht –“
„Verlassen Sie das Unternehmen, verlassen Sie es, nutzen Sie den richtigen Job für das Werkzeug. Verlassen Sie das Unternehmen.“
Für mich ist GoLang wie eine arrangierte Ehe, bei der man zwar nie das Rauschen in seinem Herzen spürt, aber nie im Stich lässt, es ist der Begleiter auf Lebens- und Lebensweg, auf den man sein ganzes Leben wetten kann es.
Aber mein Freund, wenn Sie auf der Suche nach diesem Ansturm sind, lesen Sie weiter!
Aber – aber ich will diesen Ansturm … ich möchte fühlen, wie mein Herz explodiert, wenn ich nur einen Blick auf ihre Ey-Syntax erhasche … ich möchte das Gefühl haben, im Himmel zu sein, wenn ich bei ihnen und in ihnen bin Zum Teufel, wenn ich nicht...
Werfen wir einen kurzen Blick auf ein Beispiel für Multithread-Sicherheit in 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); }
Wir haben einen Heap-zugewiesenen Wert und es gibt 10 Threads, die versuchen, ihn unabhängig zu ändern.
Dieser Code greift unsicher auf die Zählervariable zu, da alle Threads versuchen, den Zähler gleichzeitig zu ändern.
In anderen Sprachen lässt sich ähnlicher Code problemlos kompilieren und ausführen.
Wenn Sie schon einmal in einer Multithread-Umgebung gearbeitet haben, könnte Ihr erster Gedanke darin bestehen, einen „Mutex“ zu verwenden, um Race Conditions beim Aktualisieren der Zählervariablen zu verhindern.
Aber es ist leicht, solche kleinen Dinge in einer großen Codebasis aufgrund menschlicher Fehler zu übersehen.
Rust lässt dieses Programm nicht einmal kompilieren.
Aufgrund der Eigentums- und Ausleihregeln erkennt der Compiler, dass Sie im ersten Thread in der ersten Iteration der for-Schleife einen veränderlichen Ausleihzähler verwenden... bis jetzt ok... der zweiten Iteration Willst du parallel auch wechselseitig Zähler ausleihen? unsicher! löst einen COMPILE-TIME-FEHLER!! aus.
Das Referenzieren oder „Ausleihen“ eines Werts von seinem Eigentümer mit der Absicht, ihn zu verändern/zu modifizieren, wird als „veränderliches Ausleihen“ bezeichnet
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); }
In Situationen wie diesen geben andere Sprachen überhaupt keinen Fehler aus. Es liegt in Ihrer Verantwortung, die Richtigkeit zu überprüfen, Rust verhindert dies.
Konstruktionen wie diese, die über die gesamte Sprache verteilt sind, helfen Ihnen, sich nicht (oft) selbst ins Bein zu schießen.
ES Hängt davon ab!
Ich wirklich wünschte, es gäbe eine Sprache, die die Antwort wäre, und selbst wenn GoLang dem ziemlich nahe kommt, hängt es wirklich von Ihrem Anwendungsfall und vor allem von Ihrem Team ab.
Für mich ist es eine Freude, mit Rust zusammenzuarbeiten (im Moment, wer weiß... hehe)
Die Leute von TigerBeetle haben die Chance auf Zig genutzt und sind damit zufrieden.
Primeagen ist zufriedener mit Zig.
Für Jarred Sumner ist Zig in Ordnung, er hat Bun in Zig geschrieben.
Mitchell Hashimoto (der Typ hinter HashiCorp) schreibt gespenstisch in Zig, einem BLITZSCHNELLEN Begriff –
.
.
.
Warte...
Das obige ist der detaillierte Inhalt vonIch habe jede beliebte Programmiersprache ausprobiert. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!