Zo uit de eerste hand zijn er duidelijke verschillen tussen Go en Rust. Go is sterker gericht op het bouwen van web-API’s en kleine diensten die eindeloos kunnen schalen, vooral met de kracht van goroutines. Dit laatste is ook mogelijk met Rust, maar het is veel moeilijker vanuit het oogpunt van ontwikkelaarservaring.
Rust werkt goed voor het verwerken van grote hoeveelheden gegevens en andere CPU-intensieve bewerkingen, zoals het uitvoeren van algoritmen. Dit is het grootste voordeel van Rust ten opzichte van Go. Projecten die hoge prestaties vereisen zijn over het algemeen beter geschikt voor Rust.
In deze tutorial vergelijken en contrasteren we Go en Rust, waarbij we elke programmeertaal evalueren op prestaties, concurrency, geheugenbeheer en de algehele ontwikkelaarservaring. We presenteren ook een overzicht van deze elementen om u te helpen in een oogopslag de juiste taal voor uw project te kiezen.
Als u net begint met Rust, is het misschien een goed idee om deze beginnershandleiding op te frissen voordat u verder leest.
Als u helemaal op de hoogte bent, laten we er dan in duiken!
Prestaties
Orspronkelijk ontworpen door ingenieurs van Google, werd Go in 2009 aan het publiek geïntroduceerd. Het werd gemaakt om een alternatief te bieden voor C++ dat gemakkelijker te leren en te coderen was en geoptimaliseerd was om op multicore CPU’s te draaien.
Sindsdien is Go geweldig voor ontwikkelaars die willen profiteren van de concurrency die de taal biedt. De taal biedt goroutines die je in staat stellen om functies als subprocessen uit te voeren.
Een groot voordeel van Go is hoe gemakkelijk je goroutines kunt gebruiken. Door simpelweg de syntax go
aan een functie toe te voegen, wordt deze uitgevoerd als een subproces. Go’s concurrency model maakt het mogelijk om werklasten uit te rollen over meerdere CPU cores, waardoor het een zeer efficiënte taal is.
package mainimport ( "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")}
Ondanks de multicore CPU ondersteuning, slaagt Rust er nog steeds in om Go te overtreffen. Rust is efficiënter in het uitvoeren van algoritmen en resource-intensieve operaties. De Benchmarks Game vergelijkt Rust en Go voor verschillende algoritmen, zoals binaire bomen. Voor alle geteste algoritmen was Rust ten minste 30 procent sneller; in het geval van binaire boomberekeningen was dat tot 1.000 procent. Een onderzoek van Bitbucket laat vergelijkbare resultaten zien, waarbij Rust op gelijke hoogte presteert met C++.
(Bron: Benchmarks Game)
Concurrency
Zoals hierboven vermeld, ondersteunt Go concurrency. Laten we bijvoorbeeld zeggen dat je een webserver hebt die API-verzoeken verwerkt. U kunt Go’s goroutines gebruiken om elk verzoek als een subproces uit te voeren, waardoor de efficiëntie wordt gemaximaliseerd door taken naar alle beschikbare CPU-kernen te offloaden.
Goroutines maken deel uit van Go’s ingebouwde functies, terwijl Rust alleen native async/await-syntaxis heeft ontvangen om gelijktijdigheid te ondersteunen. Als zodanig gaat de ontwikkelaarservaring naar Go als het gaat om concurrency. Rust is echter veel beter in het garanderen van geheugenveiligheid.
Hier is een voorbeeld van vereenvoudigde threads voor 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!");}
Concurrency is altijd een netelig probleem geweest voor ontwikkelaars. Het is geen gemakkelijke taak om geheugenveilige concurrency te garanderen zonder de ervaring van de ontwikkelaar in gevaar te brengen. Deze extreme focus op veiligheid heeft echter geleid tot de creatie van bewijsbaar correcte concurrency. Rust experimenteerde met het concept van eigendom om ongevraagde toegang tot bronnen te voorkomen om geheugenveiligheidsbugs te voorkomen.
Rust biedt vier verschillende concurrency paradigma’s om u te helpen veelvoorkomende geheugenveiligheidsvalkuilen te vermijden. We zullen twee veel voorkomende paradigma’s nader bekijken: kanaal en slot.
Kanaal
Een kanaal helpt bij het overbrengen van een bericht van de ene thread naar de andere. Hoewel dit concept ook bestaat voor Go, kunt u met Rust een pointer van de ene thread naar de andere overbrengen om race condities voor bronnen te vermijden. Door het doorgeven van pointers, kan Rust thread isolatie voor kanalen afdwingen. Opnieuw toont Rust zijn obsessie met geheugenveiligheid in relatie tot zijn concurrency model.
Lock
Gegevens zijn alleen toegankelijk als het lock is vastgehouden. Rust vertrouwt op het principe van het vergrendelen van gegevens in plaats van code, die vaak wordt gevonden in programmeertalen zoals Java.
Voor meer details over het concept van eigendom en alle concurrency paradigma’s, bekijk “Fearless Concurrency with Rust.”
Geheugenveiligheid
Het eerdere concept van eigendom is een van de belangrijkste verkoopargumenten van Rust. Rust tilt typeveiligheid, die ook belangrijk is voor het mogelijk maken van geheugenveilige concurrency, naar een hoger niveau.
Volgens de Bitbucket blog, “controleert de zeer strenge en pedante compiler van Rust elke variabele die je gebruikt en elk geheugenadres waarnaar je verwijst. Het voorkomt mogelijke data race-condities en informeert u over ongedefinieerd gedrag.”
Dit betekent dat u niet zult eindigen met een buffer overflow of een race conditie als gevolg van de extreme obsessie van Rust met geheugenveiligheid. Dit heeft echter ook zijn nadelen. Je moet je bijvoorbeeld hyperbewust zijn van geheugentoewijzingsprincipes terwijl je code schrijft. Het is niet eenvoudig om altijd je geheugenbeveiliging op orde te hebben.
Ontwikkelaarservaring
Laten we eerst eens kijken naar de leercurve die bij elke taal hoort. Go is ontworpen met eenvoud in het achterhoofd. Ontwikkelaars noemen het vaak een “saaie” taal, wat wil zeggen dat de beperkte set ingebouwde functies Go eenvoudig te adopteren maakt.
Daarnaast biedt Go een eenvoudiger alternatief voor C++, waarbij aspecten als geheugenveiligheid en geheugentoewijzing verborgen blijven. Rust kiest een andere benadering en dwingt je om na te denken over concepten als geheugenveiligheid. Het concept van eigendom en de mogelijkheid om pointers door te geven maakt Rust een minder aantrekkelijke optie om te leren. Als je constant nadenkt over geheugenveiligheid, ben je minder productief en zal je code ongetwijfeld comlexer zijn.
De leercurve voor Rust is behoorlijk steil vergeleken met Go. Het is echter vermeldenswaard dat Go een steilere leercurve heeft dan meer dynamische talen zoals Python en JavaScript.
Wanneer Go te gebruiken
Go werkt goed voor een breed scala aan use cases, waardoor het een geweldig alternatief is voor Node.js voor het maken van web-API’s. Zoals opgemerkt door Loris Cro, “Go’s concurrency model is een goede pasvorm voor server-side applicaties die meerdere onafhankelijke verzoeken moeten afhandelen”. Dit is precies waarom Go goroutines biedt.
Wat meer is, Go heeft ingebouwde ondersteuning voor het HTTP web protocol. Je kunt snel een kleine API ontwerpen met behulp van de ingebouwde HTTP-ondersteuning en deze uitvoeren als een microservice. Daarom past Go goed in de microservices-architectuur en voorziet het in de behoeften van API-ontwikkelaars.
Kortom, Go is een goede pasvorm als u waarde hecht aan ontwikkelsnelheid en de voorkeur geeft aan eenvoud van syntaxis boven prestaties. Bovendien biedt Go een betere leesbaarheid van de code, wat een belangrijk criterium is voor grote ontwikkelteams.
Kies Go wanneer:
- U geeft om eenvoud en leesbaarheid
- U een eenvoudige syntaxis wilt om snel code te schrijven
- U een flexibelere taal wilt gebruiken die webontwikkeling ondersteunt
Wanneer u Rust gebruikt
Rust is een goede keuze wanneer prestaties belangrijk zijn, zoals wanneer u grote hoeveelheden data verwerkt. Bovendien geeft Rust u fijnkorrelige controle over hoe threads zich gedragen en hoe bronnen worden gedeeld tussen threads.
Aan de andere kant komt Rust met een steile leercurve en vertraagt het de ontwikkelsnelheid door de extra complexiteit van geheugenveiligheid. Dit is niet noodzakelijkerwijs een nadeel; Rust garandeert ook dat u geen geheugenveiligheidsbugs zult tegenkomen omdat de compiler elke datapointer controleert. Voor complexe systemen kan deze zekerheid van pas komen.
Kies Rust wanneer:
- U om prestaties geeft
- U fijnkorrelige controle over threads wilt
- U geheugenveiligheid belangrijker vindt dan eenvoud
Go vs. Rust: My honest take
Laten we beginnen met het benadrukken van de overeenkomsten. Zowel Go als Rust zijn open-source en ontworpen om de microservices architectuur en parallelle computeromgevingen te ondersteunen. Beiden optimaliseren het gebruik van de beschikbare CPU cores door middel van concurrency.
Maar aan het eind van de dag, welke taal is het beste?
Er zijn vele manieren om deze vraag te benaderen. Ik zou aanraden om na te denken over wat voor soort applicatie je wilt bouwen. Go is goed voor het maken van webtoepassingen en API’s die profiteren van de ingebouwde concurrency-functies en tegelijkertijd de microservices-architectuur ondersteunen.
U kunt Rust ook gebruiken om een web-API te ontwikkelen, maar het is niet ontworpen met deze use-case in het achterhoofd. De focus van Rust op geheugenveiligheid verhoogt de complexiteit en de ontwikkeltijd, vooral voor een vrij eenvoudige web-API. De grotere hoeveelheid controle die u over uw code hebt, stelt u echter in staat om meer geoptimaliseerde, geheugenefficiënte en performante code te schrijven.
Om het zo eenvoudig mogelijk te stellen, het Go versus Rust debat is eigenlijk een kwestie van eenvoud versus veiligheid.
Voor meer perspectieven, bekijk “Kiezen tussen Go en Rust.”
LogRocket: Volledig inzicht in productie Rust-toepassingen
Het debuggen van Rust-toepassingen kan lastig zijn, vooral wanneer gebruikers problemen ondervinden die moeilijk te reproduceren zijn. Als u geïnteresseerd bent in het monitoren en volgen van de prestaties van uw Rust applicaties, het automatisch aan het licht brengen van fouten, en het volgen van trage netwerk requests en laadtijd, probeer dan LogRocket.
LogRocket is als een DVR voor webapps en registreert letterlijk alles wat er op uw Rust-app gebeurt. In plaats van te gissen naar de oorzaak van problemen, kunt u de status van uw applicatie samenvoegen en rapporteren wanneer een probleem optrad. LogRocket bewaakt ook de prestaties van uw app en rapporteert statistieken zoals CPU-belasting, client-geheugengebruik en meer.
Moderniseer de manier waarop u uw Rust-apps debugt – begin gratis met bewaking.