I’ve worked with languages like JavaScript and Go, and I enjoyed both for different reasons.
JavaScript gave me speed and flexibility. Go gave me simplicity and practical concurrency.
Then I met Rust and at first, it felt difficult.
But once I understood how Rust handles memory without a garbage collector, I fell in love with it.
Memory Safety Without a Garbage Collector
Most modern languages solve memory management with a garbage collector (GC).
A GC periodically finds memory that is no longer used and frees it automatically.
Rust takes a different path:
- No runtime garbage collector
- No manual
free()like in C - Memory safety guaranteed at compile time (in most cases)
Rust uses three core ideas:
- Ownership
- Borrowing
- Lifetimes
These rules are checked by the compiler before your program runs.
1) Ownership: One Owner at a Time
In Rust, every value has a single owner.
When the owner goes out of scope, Rust automatically drops the value and frees memory.
{
let s = String::from("hello");
// s owns the string memory here
} // s goes out of scope, memory is freed automatically
This avoids memory leaks and double-frees in normal code paths, without needing a GC pause.
2) Borrowing: Use Data Without Taking Ownership
Instead of copying or transferring ownership all the time, Rust lets you borrow references:
- Immutable borrow:
&T - Mutable borrow:
&mut T
But Rust enforces strict aliasing rules:
- Many immutable references OR
- One mutable reference
- Not both at the same time
This rule prevents data races at compile time.
3) Lifetimes: References Must Always Be Valid
Lifetimes describe how long references are valid.
Often, Rust infers lifetimes automatically. When needed, you can annotate them.
This helps prevent dangling references references to memory that no longer exists.
How Rust “Behaves” in Practice
When writing Rust, you feel the compiler acting like a strict mentor:
- “Who owns this value?”
- “How long does this reference live?”
- “Are you mutating while also sharing?”
- “Could this reference outlive its data?”
At first, this feels like friction.
Later, it feels like protection.
The compiler catches entire classes of bugs before runtime:
- Use-after-free
- Double free
- Null-like reference misuse
- Data races in concurrent code
Why It Feels Hard (Especially Coming from JavaScript and Go)
From JavaScript to Rust
JavaScript is highly dynamic and forgiving.
You can move fast, but many errors appear at runtime.
Rust is the opposite: strict upfront, safer later.
From Go to Rust
Go has garbage collection and a simpler mental model.
Rust asks you to think more deeply about ownership and borrowing.
In Go, many programs compile quickly and run fine, but some memory/concurrency issues emerge later.
In Rust, many of those issues are rejected during compilation.
Why I Fell in Love with Rust
Even though Rust is harder, I love it because:
- It gives low-level control with high-level safety
- It avoids GC pauses while staying memory-safe
- It makes concurrency safer by default
- It turns the compiler into a collaborator
- It teaches better engineering habits
Rust doesn’t just help me write code that works.
It helps me write code I can trust.
Final Thought
Rust has a steep learning curve especially if you come from JavaScript or Go.
But once ownership and borrowing click, the difficulty starts to feel meaningful.
For me, Rust changed how I think about memory, correctness, and software design.
That’s why I fell in love with it.
Top comments (0)