How to Code in Rust: A Step-by-Step Guide for Beginners

2026-06-05·Getting Started

Key Takeaways

  • Rust guarantees memory safety without a garbage collector, using a strict ownership model checked at compile time.
  • Start with the Rust toolchain (rustup, cargo) and build a simple CLI tool in under 30 minutes.
  • Master ownership, borrowing, and lifetimes first—they’re the hardest part but essential for safe systems programming.
  • Async in Rust is different from JavaScript or Python; use tokio for practical concurrency.

---

Why Learn Rust in 2025?

Rust has been Stack Overflow’s most loved language for 8 years running. It powers everything from Firefox’s rendering engine (Servo) to Discord’s backend and AWS’s infrastructure. The compiler catches memory bugs at compile time—no segfaults, no null pointer exceptions—and it’s as fast as C++.

I started Rust three years ago after hitting a wall with C++ memory management on a network server project. The learning curve is steep, but once ownership clicks, it changes how you think about code.

Step 1: Install Rust and Write Your First Program

Open a terminal and run:

```bash

curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

```

This installs `rustup`, which manages Rust versions. Then:

```bash

rustc --version # should show 1.80+ (as of 2025)

cargo --version # package manager and build tool

```

Create a new project:

```bash

cargo new hello_rust

cd hello_rust

```

Edit `src/main.rs`:

```rust

fn main() {

println!("Hello, Rust!");

}

```

Build and run:

```bash

cargo run

```

That’s it. `cargo run` compiles and executes in one step. The binary lives in `target/debug/`.

Step 2: Ownership – The Hardest Part (But Worth It)

Every value in Rust has a single *owner*. When the owner goes out of scope, the value is dropped. This replaces garbage collection.

Example:

```rust

let s1 = String::from("hello");

let s2 = s1; // s1 is *moved* to s2. s1 is now invalid.

println!("{}", s1); // Compiler error!

```

To keep both, clone explicitly:

```rust

let s1 = String::from("hello");

let s2 = s1.clone();

println!("{}", s1); // Works

```

Why this matters: No double-free bugs. No dangling pointers. The compiler enforces this at build time. In C++, the same pattern would compile but crash at runtime.

Step 3: Borrowing and References

Instead of moving data, you can *borrow* it with `&`:

```rust

fn calculate_length(s: &String) -> usize {

s.len()

} // s goes out of scope, but doesn't drop the value

let s = String::from("hello");

let len = calculate_length(&s);

println!("{}", s); // Still works

```

Two rules:

  • At any time, you can have either one mutable reference or any number of immutable references.
  • References must always be valid (no dangling pointers).

Step 4: Build a CLI Tool (Your First Real Project)

Let’s make a `grep`-like tool. Create a new project:

```bash

cargo new minigrep

cd minigrep

```

Add dependencies in `Cargo.toml`:

```toml

[dependencies]

clap = { version = "4.5", features = ["derive"] }

```

Write `src/main.rs`:

```rust

use clap::Parser;

use std::fs;

#[derive(Parser)]

struct Cli {

pattern: String,

path: std::path::PathBuf,

}

fn main() {

let args = Cli::parse();

let content = fs::read_to_string(&args.path)

.expect("Could not read file");

for line in content.lines() {

if line.contains(&args.pattern) {

println!("{}", line);

}

}

}

```

Run with:

```bash

cargo run -- "hello" src/main.rs

```

This reads a file and prints lines matching a pattern. The `clap` crate handles argument parsing, which is much cleaner than manual string splitting.

Step 5: Systems Programming with Raw Pointers (When Needed)

Rust supports unsafe code for hardware interaction, FFI, or performance hotspots:

```rust

let mut num = 5;

let r1 = &num as *const i32;

let r2 = &mut num as *mut i32;

unsafe {

println!("r1: {}", *r1);

*r2 = 10;

}

```

Use `unsafe` sparingly—it’s a contract that you’ve manually checked invariants the compiler can’t verify. In practice, 95% of your code should be safe Rust.

Step 6: Async Programming – The Rust Way

Rust’s async model is zero-cost: no runtime overhead unless you use it. The most popular runtime is `tokio`.

Add to `Cargo.toml`:

```toml

tokio = { version = "1.40", features = ["full"] }

```

Example async HTTP request:

```rust

use tokio::net::TcpStream;

use tokio::io::AsyncWriteExt;

#[tokio::main]

async fn main() -> Result<(), Box> {

let mut stream = TcpStream::connect("example.com:80").await?;

stream.write_all(b"GET / HTTP/1.1\r\nHost: example.com\r\n\r\n").await?;

Ok(())

}

```

Comparison: Rust vs JavaScript vs Go async

FeatureRust (tokio)JavaScript (async/await)Go (goroutines)

------------
Runtime size~100KB (can be smaller)10-30MB (V8)2MB+ (minimum)
Stack per taskFixed 2KB (reusable)1-4MB (full thread)4KB (growable)
CancellationExplicit (drop the future)No built-inVia context
Learning curveSteep (lifetimes + async)ModerateLow

Tokio tasks are lightweight—you can spawn 10,000 concurrently without breaking a sweat. The tradeoff is you must think about ownership across .await points.

Next Steps

  • Build a small web server with `axum` or `actix-web`.
  • Contribute to an open-source Rust project (look for “good first issue” labels).
  • Read *The Rust Programming Language* (free online).

Rust is not easy, but it rewards patience. The first week is frustrating; the first month is illuminating; after a year, you’ll wonder how you ever lived without the compiler catching your mistakes.

---

FAQ

Q: Is Rust hard for beginners with no systems programming experience?

A: Yes, initially. The ownership model is unique and takes time to internalize. But if you’ve struggled with C++ memory bugs, Rust’s compiler is a lifesaver. Start with small CLI tools, not full-fledged OS kernels.

Q: How long does it take to learn Rust to a professional level?

A: Most developers report 3–6 months of daily practice to feel productive. The first 2 weeks are the hardest—focus on ownership, borrowing, and lifetimes without skipping ahead to async.

Q: Can I use Rust for web development?

A: Absolutely. Frameworks like `axum`, `actix-web`, and `rocket` are production-ready. They offer performance comparable to Go or Node.js with better memory safety. Many companies (Discord, Figma, Cloudflare) use Rust for performance-critical web services.