DEV Community

Cover image for Rust vs Go: Choosing Your Backend Language 🚀
Bruno Ciccarino λ for learn go

Posted on

Rust vs Go: Choosing Your Backend Language 🚀

Thinking about Rust and Go for your backend? Let’s break down what makes each language tick so you can pick the one that best fits your project!

Credits: typescript-vs-go

🌟 Quick Comparison

Feature Go Rust
Performance fast Extremely fast, optimized for performance
Concurrency Built-in (goroutines) Built-in (async/await, plus threads)
Type System Static, simpler Static, strict, with powerful compile-time checks
Memory Safety Basic manual checks Ensures memory safety without garbage collection
Ecosystem Growing Growing, with strong community support (Cargo)
Use Cases Microservices, systems programming Systems programming, performance-critical applications

Now, let’s dive deeper! 🎉

🔱 Type Systems: Rust vs Go
Rust and Go both aim for type safety, but with different philosophies.

Type Safety: Locking Things Down 🔒

Rust: Rust takes safety super seriously. If you try to use the wrong type or make a mistake that could lead to memory leaks, Rust won’t let your code run. Rust also has “ownership” and “borrowing” concepts to keep data safe and manage memory efficiently.

fn greet(name: &str) -> String {
    format!("Hello, {}", name)
}
greet(123); // Nope! Rust won’t compile this.
Enter fullscreen mode Exit fullscreen mode

Go: Go keeps it straightforward. Every variable has a type, and Go catches mismatches at compile time. No guesswork here!

func greet(name string) string {
    return "Hello, " + name
}
greet(123) // Compilation error: type mismatch!
Enter fullscreen mode Exit fullscreen mode

Type Inference: How Much Guesswork? 🔍

Rust: Rust’s type inference is pretty powerful but not magic. It’ll infer types in functions and closures, which can save some typing. It’s strict but flexible enough.

let age = 25; // inferred as i32

Go: Go’s inference is basic but handy. You can use := for shorthand type inference.

age := 25 // inferred as int

Generics: Code Reusability đŸ§©

Rust: Rust’s generics are robust, and the compiler ensures they’re used safely. You can do lots of advanced tricks with them!

fn print_value<T: std::fmt::Display>(value: T) {
    println!("{}", value);
}
Enter fullscreen mode Exit fullscreen mode

Go: Go added generics in version 1.18, and they keep things straightforward. Go’s generics are great for simplicity but lack some of Rust’s advanced features.

func Print[T any](value T) {
    fmt.Println(value)
}
Enter fullscreen mode Exit fullscreen mode

⚡ Concurrency: Go’s Goroutines vs Rust’s Async/Await
Concurrency is where both languages shine—each in its own way!

Go: Concurrency in Go is as easy as adding the go keyword in front of a function to spawn a goroutine. Simple, effective, and great for I/O-bound tasks.

go func() {
    fmt.Println("Running concurrently in Go!")
}()
Enter fullscreen mode Exit fullscreen mode

Rust: Rust uses async/await for concurrency. It’s a little more verbose than Go, but extremely powerful, with no risk of data races thanks to Rust’s ownership rules.

async fn say_hello() {
    println!("Hello from Rust async!")
}
Enter fullscreen mode Exit fullscreen mode

🐛 Error Handling: A Tale of Two Approaches
Rust and Go make you deal with errors head-on, but they go about it differently.

Rust: Rust takes a “Result” and “Option” approach, which is strict but safe. No nulls or unhandled errors slipping through!

fn read_file() -> Result<String, std::io::Error> {
    std::fs::read_to_string("file.txt")
}
Enter fullscreen mode Exit fullscreen mode

Go: Go has error handling down to an art. It’s verbose, but simple. You check for errors after every operation.

file, err := os.Open("file.txt")
if err != nil {
    // Handle it
}
Enter fullscreen mode Exit fullscreen mode

đŸ’» Developer Ecosystem and Tooling
Both languages have strong communities and tool support, but they focus on different use cases.

Rust: Rust has Cargo, a fantastic package manager and build system that makes dependency management a breeze. Cargo handles everything from testing to documentation with ease!
Go: Go has Go Modules, a simple system for managing dependencies. It’s not as feature-rich as Cargo, but it does the job well and keeps things organized.

⚙ Speed and Scalability
Rust and Go are both known for their performance, but they handle it differently.

Rust: With near C-level performance, Rust is perfect for high-performance applications. It’s compiled directly to machine code, making it blazing fast.
Go: Go is fast and efficient, though it’s slightly slower than Rust. However, it’s built for quick compilation and deployment, and for most web backends, Go’s speed is more than enough.

🔍 Popular Frameworks and Libraries
Both languages come with a rich set of tools, though they vary widely:

Rust:

Actix-Web: High-speed web framework built on Rust’s async model.
Rocket: Another popular framework with a focus on ease of use and performance.
Tide: Built for async-first applications, great for microservices.

Go:

Gin: Lightweight framework ideal for REST APIs.
Echo: Known for its simplicity and HTTP/2 support.
Beego: Great for MVC-style web applications.

Community & Learning Resources
Both languages have vibrant communities and learning resources, but Rust’s community is a bit more passionate due to its steep learning curve. Go’s community is practical and welcoming, ideal for beginners!

🚀 Final Takeaway: Rust vs Go
So, which one’s for you? Here’s the vibe:

Rust is for you if you’re after peak performance and have the patience for its steeper learning curve. It’s fantastic for systems programming, security-critical apps, and anything where performance is key.

Go is your go-to if you’re building web servers, microservices, or need a language that’s easy to learn and deploy. Its simplicity and concurrency model make it a dream for scalable backend applications.

Whichever path you choose, Rust and Go are both powerful tools with unique strengths.

Top comments (18)

Collapse
 
mykhailokrainik profile image
Mykhailo Krainik

However, it should be noted that in large projects using Go with goroutines, there is often at least one "data racing", whereas Rust avoids this issue. Additionally, Go lacks built-in doctests, whereas Rust includes them, making it much easier to keep documentation up-to-date.

While I’m not certain about Go’s capabilities in this area, Rust’s strong type system makes significant object refactoring much easier. Rust’s type system guarantees ensure that if a program compiles, you can have confidence in its stability. This is particularly beneficial in a microservice architecture, where you need assurances that one service won’t disrupt the data processing sequence—a level of reliability that Rust inherently provides.

That said, Rust has its own set of challenges, such as issues with colored functions (sync - async problem). Some error messages, particularly in libraries like Diesel, can be extremely difficult to understand.

Collapse
 
tsolan profile image
Eugene

How have you determined/counted that?
You either lock data with mutex or don’t. Not the problem of the language.
Rust still does not guarantee performance: it’s much easier to build inefficient model in Rust due to complexity of the language than in Go.

Collapse
 
mykhailokrainik profile image
Mykhailo Krainik

That's right, Rust is not for beginners and you should understand what you are doing.

Collapse
 
pmbanugo profile image
Peter Mbanugo

however, it should be noted that in large projects using Go with goroutines, there is often at least one "data racing", whereas Rust avoids this issue.

Maybe those are projects you worked in that has programmers who don't understand Go's concurrency model and the side effects of a shared data. Go has synchronisation and Mutex which can be used to avoid race conditions. Rust avoids this by design, but it doesn't mean you can't use shared mutable state, you'd have to do it explicitly. ANd for that, Rust also provide Mutex for such situation.

Talking about their concurrency model, threads in Go are lightweight than Rust. Rust threads would use more memory than their Go counterpart, and requires more overhead to create than in Go. They both have their place and for some type of applications the differences are negligible. That's what I expected from the article, given that it's making comparison rather than just saying:

It’s a little more verbose than Go, but extremely powerful, with no risk of data races thanks to Rust’s ownership rules..

Collapse
 
mykhailokrainik profile image
Mykhailo Krainik

Could you provide some performance measurements to prove your point "Rust threads would use more memory than their Go counterpart", for example on datasets of 1,000 threads and 500,000 threads for both languages ​​so we can compare them?

Thread Thread
 
pmbanugo profile image
Peter Mbanugo

I guess you're familiar with both from your comment. SO you could run your own benchmark. Or google and reference the docs.

Rust uses OS threads which requires more overhead to create or pass message to. Go uses lightweight threads controlled instantiated in the userspace and controlled by the Go runtime. Erlang VM uses lightweight processes controlled by the Erlang VM, I think even more lightweight than Go's threads.

When it comes to performance, there's no straight telling that one languages performs faster in every kind of application. So you have to do your own benchmark, for your specific usecase.

For your Rust ref, this is one part of the docs that can give you a hint: doc.rust-lang.org/book/ch16-01-thr...

Collapse
 
brunociccarino profile image
Bruno Ciccarino λ

Good observation

Collapse
 
xuanlong5 profile image
xuanlong

gRPC in Golang's ecosytem is the best right now.

Collapse
 
kimss profile image
kelvin isaac phiri • Edited

Awasome, so helpful

Collapse
 
tsolan profile image
Eugene

Async requires runtimes and it does not come with the language itself.

Collapse
 
djnoslen3664 profile image
Pablo Carmona SĂĄnchez

If I want to become a cyber security developer/analyst which language should I go with?

Collapse
 
brunociccarino profile image
Bruno Ciccarino λ

I would choose C++ or C and Python for cybersecurity, with C++ you go much deeper into how the computer works, or how networks work, etc... But if you are a beginner in the programming area I recommend starting with Python and then progressing to a C or a C++

Collapse
 
vemareddy_shrishveshredd profile image
VEMAREDDY SHRISHVESH REDDY 22115161

I just choose rust but got to know mid that rust is not a destination , It is a journey .

Collapse
 
khodyrev_ivan profile image
Ivan Khodyrev

Just pick Java or C# and you will be good. Go and Rust have their benefits for sure, but they lack expressive power and are a bit too low level for wide range of tasks. I mean writing high level code usually needs focussing on exact logic of a domain, but in Go your code will be full of excessive error handling stuff as well as "for" cycles, which make the code hardly readable and in Rust you will find yourself fighting the borrow checker and cryptic symbols a bit too much, rather than solving the real domain problems which are your actual goal in the end.

Collapse
 
sulaim_saed profile image
Sulaim Zaed

Good one

Collapse
 
martinhaeusler profile image
Martin HĂ€usler

Backend? As in "server backend"? I default to JVM unless there's a damn good reason not to.

Collapse
 
skysingh04 profile image
Akash Singh

Honestly I feel like Rust and Go are languages are separate a normal everyday javascript / python developer with actual developers. Controversial but true! These two languages are more preferred by people who love to build software xD