D’emblée, il y a des différences claires entre Go et Rust. Go est davantage axé sur la construction d’API web et de petits services qui peuvent évoluer à l’infini, notamment grâce à la puissance des goroutines. Ce dernier point est également possible avec Rust, mais les choses sont beaucoup plus difficiles du point de vue de l’expérience du développeur.
Rust fonctionne bien pour le traitement de grandes quantités de données et d’autres opérations gourmandes en CPU, comme l’exécution d’algorithmes. C’est le plus grand avantage de Rust par rapport à Go. Les projets qui exigent des performances élevées sont généralement mieux adaptés à Rust.
Dans ce tutoriel, nous allons comparer et opposer Go et Rust, en évaluant chaque langage de programmation pour les performances, la concurrence, la gestion de la mémoire et l’expérience globale du développeur. Nous présenterons également une vue d’ensemble de ces éléments pour vous aider à choisir le bon langage pour votre projet en un coup d’œil.
Si vous débutez avec Rust, il pourrait être judicieux de réviser ce guide du débutant avant de poursuivre votre lecture.
Si vous êtes bien accroché, plongeons dans le vif du sujet !
Performance
Initialement conçu par les ingénieurs de Google, le Go a été présenté au public en 2009. Il a été créé pour offrir une alternative au C++ qui était plus facile à apprendre et à coder et était optimisé pour fonctionner sur les CPU multicœurs.
Depuis lors, Go a été formidable pour les développeurs qui veulent profiter de la concurrence que le langage offre. Le langage fournit des goroutines qui vous permettent d’exécuter des fonctions en tant que sous-processus.
Un grand avantage de Go est la facilité avec laquelle vous pouvez utiliser les goroutines. Il suffit d’ajouter la syntaxe go
à une fonction pour qu’elle s’exécute comme un sous-processus. Le modèle de concurrence de Go vous permet de déployer des charges de travail sur plusieurs cœurs de CPU, ce qui en fait un langage très efficace.
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")}
Malgré le support des CPU multicœurs, Rust parvient toujours à surpasser Go. Rust est plus efficace dans l’exécution des algorithmes et des opérations gourmandes en ressources. Le jeu des benchmarks compare Rust et Go pour divers algorithmes, tels que les arbres binaires. Pour tous les algorithmes testés, Rust est au moins 30 % plus rapide ; dans le cas des calculs d’arbres binaires, la différence peut atteindre 1 000 %. Une étude de Bitbucket montre des résultats similaires dans lesquels Rust a des performances équivalentes à celles du C++.
(Source : Benchmarks Game)
Concurrence
Comme mentionné ci-dessus, Go supporte la concurrence. Par exemple, disons que vous exécutez un serveur web qui gère les demandes d’API. Vous pouvez utiliser les goroutines de Go pour exécuter chaque requête en tant que sous-processus, maximisant ainsi l’efficacité en déchargeant les tâches sur tous les cœurs de CPU disponibles.
Les goroutines font partie des fonctions intégrées de Go, tandis que Rust n’a reçu que la syntaxe native async/await pour supporter la simultanéité. En tant que tel, l’avantage de l’expérience du développeur va à Go quand il s’agit de la concurrence. Cependant, Rust est bien meilleur pour garantir la sécurité de la mémoire.
Voici un exemple de threads simplifiés pour 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!");}
La simultanéité a toujours été un problème épineux pour les développeurs. Ce n’est pas une tâche facile de garantir une simultanéité sûre pour la mémoire sans compromettre l’expérience du développeur. Cependant, cette focalisation extrême sur la sécurité a conduit à la création d’une concurrence provablement correcte. Rust a expérimenté le concept de propriété pour empêcher l’accès non sollicité aux ressources afin d’éviter les bugs de sécurité de la mémoire.
Rust offre quatre paradigmes de concurrence différents pour vous aider à éviter les pièges courants de sécurité de la mémoire. Nous allons examiner de plus près deux paradigmes communs : channel et lock.
Channel
Un channel permet de transférer un message d’un thread à un autre. Bien que ce concept existe également pour Go, Rust permet de transférer un pointeur d’un thread à un autre pour éviter les conditions de course pour les ressources. En passant des pointeurs, Rust peut renforcer l’isolation des threads pour les canaux. Encore une fois, Rust affiche son obsession pour la sécurité de la mémoire en ce qui concerne son modèle de concurrence.
Lock
Les données ne sont accessibles que lorsque le verrou est maintenu. Rust s’appuie sur le principe de verrouillage des données au lieu du code, que l’on retrouve souvent dans les langages de programmation tels que Java.
Pour plus de détails sur le concept de propriété et tous les paradigmes de concurrence, consultez « Fearless Concurrency with Rust. »
Sécurité de la mémoire
Le concept précédent de propriété est l’un des principaux arguments de vente de Rust. Rust porte la sécurité des types, qui est également importante pour permettre une concurrence sûre en mémoire, à un niveau supérieur.
Selon le blog Bitbucket, « le compilateur très strict et pédant de Rust vérifie chaque variable que vous utilisez et chaque adresse mémoire que vous référencez. Il évite les éventuelles conditions de course de données et vous informe des comportements non définis. »
Cela signifie que vous ne vous retrouverez pas avec un dépassement de tampon ou une condition de course en raison de l’obsession extrême de Rust pour la sécurité de la mémoire. Cependant, cela a aussi ses inconvénients. Par exemple, vous devez être hyper conscient des principes d’allocation de mémoire lorsque vous écrivez du code. Il n’est pas facile de toujours avoir votre garde de sécurité mémoire en place.
Expérience du développeur
D’abord, regardons la courbe d’apprentissage associée à chaque langage. Le go a été conçu dans un souci de simplicité. Les développeurs le qualifient souvent de langage « ennuyeux », ce qui revient à dire que son ensemble limité de fonctionnalités intégrées rend Go facile à adopter.
De plus, Go offre une alternative plus facile au C++, en cachant des aspects tels que la sécurité de la mémoire et l’allocation de mémoire. Rust adopte une autre approche, en vous forçant à réfléchir à des concepts tels que la sécurité de la mémoire. Le concept de propriété et la possibilité de passer des pointeurs font de Rust une option moins attrayante à apprendre. Lorsque vous êtes constamment en train de penser à la sécurité de la mémoire, vous êtes moins productif et votre code sera forcément plus comlex.
La courbe d’apprentissage de Rust est assez raide par rapport à Go. Il convient de mentionner, cependant, que Go a une courbe d’apprentissage plus raide que les langages plus dynamiques tels que Python et JavaScript.
Quand utiliser Go
Go fonctionne bien pour une grande variété de cas d’utilisation, ce qui en fait une excellente alternative à Node.js pour la création d’API Web. Comme l’a noté Loris Cro, « le modèle de concurrence de Go est bien adapté aux applications côté serveur qui doivent gérer de multiples requêtes indépendantes ». C’est exactement pourquoi Go fournit des goroutines.
De plus, Go a un support intégré pour le protocole web HTTP. Vous pouvez rapidement concevoir une petite API en utilisant le support HTTP intégré et l’exécuter comme un microservice. Par conséquent, Go s’adapte bien à l’architecture des microservices et répond aux besoins des développeurs d’API.
En bref, Go est un bon choix si vous accordez de l’importance à la vitesse de développement et préférez la simplicité de la syntaxe aux performances. En plus de cela, Go offre une meilleure lisibilité du code, ce qui est un critère important pour les grandes équipes de développement.
Choisissez Go lorsque :
- Vous vous souciez de la simplicité et de la lisibilité
- Vous voulez une syntaxe facile pour écrire rapidement du code
- Vous voulez utiliser un langage plus flexible qui prend en charge le développement web
Quand utiliser Rust
Rust est un excellent choix lorsque les performances comptent, comme lorsque vous traitez de grandes quantités de données. En outre, Rust vous donne un contrôle fin sur la façon dont les threads se comportent et comment les ressources sont partagées entre les threads.
En revanche, Rust vient avec une courbe d’apprentissage raide et ralentit la vitesse de développement en raison de la complexité supplémentaire de la sécurité de la mémoire. Ce n’est pas nécessairement un inconvénient ; Rust garantit également que vous ne rencontrerez pas de bugs de sécurité de la mémoire, car le compilateur vérifie chaque pointeur de données. Pour les systèmes complexes, cette assurance peut s’avérer pratique.
Choisissez Rust lorsque :
- Vous vous souciez des performances
- Vous voulez un contrôle à grain fin sur les threads
- Vous valorisez la sécurité de la mémoire par rapport à la simplicité
Go vs Rust : Mon avis honnête
Commençons par souligner les similitudes. Go et Rust sont tous deux open-source et conçus pour supporter l’architecture microservices et les environnements de calcul parallèle. Tous deux optimisent l’utilisation des cœurs de processeur disponibles par le biais de la concurrence.
Mais en fin de compte, quel est le meilleur langage ?
Il y a plusieurs façons d’aborder cette question. Je recommanderais de réfléchir au type d’application que vous voulez construire. Go sert bien pour la création d’applications web et d’API qui tirent parti de ses fonctionnalités de concurrence intégrées tout en supportant l’architecture microservices.
Vous pouvez également utiliser Rust pour développer une API web, mais il n’a pas été conçu avec ce cas d’utilisation à l’esprit. L’accent mis par Rust sur la sécurité de la mémoire augmente la complexité et le temps de développement, en particulier pour une API web assez simple. Cependant, la plus grande quantité de contrôle que vous avez sur votre code vous permet d’écrire un code plus optimisé, plus efficace en mémoire et plus performant.
Pour le dire aussi simplement que possible, le débat Go versus Rust est vraiment une question de simplicité versus sécurité.
Pour plus de perspectives, consultez « Choisir entre Go et Rust ».
LogRocket : Visibilité complète sur les applications Rust de production
Déboguer des applications Rust peut être difficile, surtout lorsque les utilisateurs rencontrent des problèmes difficiles à reproduire. Si vous êtes intéressé par la surveillance et le suivi des performances de vos apps Rust, la remontée automatique des erreurs et le suivi des demandes réseau lentes et du temps de chargement, essayez LogRocket.
LogRocket est comme un DVR pour les applications web, enregistrant littéralement tout ce qui se passe sur votre application Rust. Au lieu de deviner pourquoi les problèmes surviennent, vous pouvez regrouper et rapporter l’état dans lequel se trouvait votre application lorsqu’un problème est survenu. LogRocket surveille également les performances de votre app, en rapportant des métriques telles que la charge CPU du client, l’utilisation de la mémoire du client, et plus encore.
Modernisez la façon dont vous déboguez vos apps Rust – commencez à surveiller gratuitement.
.