Getting Started with Rust: Installation and First Steps

Last updated: Apr 13, 2025

1. Introduction: Why Rust?

Rust is a modern systems programming language focused on three primary goals: safety,
speed, and concurrency. It achieves memory safety (preventing common bugs like null
pointer dereferencing, buffer overflows, and data races) without needing a garbage collector, primarily
through its innovative ownership and borrowing system.

This makes Rust suitable for a wide range of applications, from low-level embedded systems and operating
systems to high-performance web servers, command-line tools, and even game development. Its strong type system
and compile-time checks catch many errors before they reach production.

This guide will walk you through installing Rust, writing your first program, and understanding the basics of
its syntax and tooling.

2. Installation withrustup

The official and recommended way to install Rust is using rustup, the Rust toolchain installer.
It manages Rust versions and associated tools like cargo (the build tool and package manager) and
rustc (the compiler).

Visit the official Rust installation page at rust-lang.org and follow the instructions for your operating system. Typically, this
involves running a single command in your terminal:

# Example for Linux/macOS (check official site for current command)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh

The installer will guide you through the process. After installation, ensure your shell environment is
configured (you might need to restart your terminal or run source $HOME/.cargo/env). Verify the
installation:

rustc --version
cargo --version

rustup also makes updating easy:

rustup update

3. Your First Rust Program: Hello, World!

Let’s create the classic “Hello, world!” program.

3.1 Writing the Code

Create a new directory for your project, e.g.,
mkdir ~/projects/hello_rust && cd ~/projects/hello_rust.
Create a file named main.rs (Rust source files use the .rs extension).
Open main.rs in your text editor and add the following code:

// main.rs

// The main function is the entry point of every executable Rust program.
fn main() {
    // println! is a macro that prints text to the console.
    println!("Hello, world!");
}
  • fn main() { … }defines the main function.

  • println!is a Rust macro (indicated by the!). Macros are a way of writing code
    that writes other code (metaprogramming).println!prints the provided string to the standard
    output, followed by a newline.

3.2 Compiling and Running

Compile the code using the Rust compiler, rustc:
rustc main.rs
This creates an executable file (named main on Linux/macOS, main.exe on Windows).

Run the executable:
# On Linux/macOS
./main

On Windows (Command Prompt)

.\main.exe

On Windows (PowerShell)

.\main

You should see the output: Hello, world!

4. Introduction to Cargo: Rust’s Build Tool & Package Manager

While rustc is fine for simple programs, most Rust projects use Cargo. Cargo
handles building code, downloading libraries (called “crates” in Rust), managing dependencies, running tests,
and more.

4.1 Creating a Cargo Project

Let’s recreate “Hello, world!” using Cargo:

Navigate to your projects directory (e.g., cd ~/projects).
Create a new project using Cargo:
cargo new hello_cargo

This command creates a new directory called hello_cargo with the following structure:
hello_cargo/
├── Cargo.toml
└── src/
└── main.rs

Cargo.toml: The configuration file for your project (metadata, dependencies). This is
called the manifest.
src/main.rs: The source code file, pre-populated with the “Hello, world!” code.

Open Cargo.toml. It will look something like this:

[package]
name = "hello_cargo"
version = "0.1.0"
edition = "2021" # Rust edition (controls language features)

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
# Crates (libraries) your project depends on go here

4.2 Building and Running with Cargo

Navigate into the new project directory: cd hello_cargo.
Build the project:
cargo build
This compiles your code and places the executable in target/debug/hello_cargo. The first build
might be slower as Cargo sets things up. Subsequent builds are faster.

Run the project:
cargo run
This command compiles the code (if necessary) and then runs the resulting executable. You should see
Hello, world! again.

Check the project for correctness without producing an executable:
cargo check
This is much faster than cargo build and useful for quickly verifying code during development.

Build an optimized release version:
cargo build --release
This creates an optimized executable in target/release/hello_cargo.

Cargo significantly simplifies the build and run process compared to using rustc directly.

4.3 Adding Dependencies

Cargo makes it easy to use libraries (crates) from the community registry, crates.io. To add a dependency (e.g., the popular rand crate for random
number generation), edit your Cargo.toml:

[dependencies]
rand = "0.8" # Add the crate name and desired version

The next time you run cargo build or cargo run, Cargo will automatically download
and compile the rand crate and its dependencies.

Alternatively, use the command line:

cargo add rand

5. Basic Rust Syntax Overview

Here’s a glimpse of some fundamental Rust syntax elements:

5.1 Variables and Mutability

Variables are immutable by default. Use the mut keyword to make them mutable.

let x = 5; // Immutable variable
let mut y = 10; // Mutable variable

// x = 6; // Error: cannot assign twice to immutable variable `x`
y = 11; // OK: `y` is mutable

5.2 Common Data Types

Rust is statically typed, meaning the compiler must know the type of every variable at compile time. It has
type inference, but you can add type annotations.

  • Integers:Signed (i8,i16,i32,i64,i128,isize) and Unsigned (u8,u16,u32,u64,u128,usize). Example:let count: i32 = 100;

  • Floating-Point:f32,f64. Example:let price: f64 = 99.99;

  • Boolean:bool(valuestrueorfalse). Example:let is_active: bool = true;

  • Character:char(single Unicode scalar value, uses single quotes). Example:let initial: char = ‘A’;

  • Tuples:Fixed-size collection of potentially different types. Example:let tup: (i32, f64, char) = (500, 6.4, ‘z’);

  • Arrays:Fixed-size collection of the same type. Example:let numbers: [i32; 5] = [1, 2, 3, 4, 5];

  • Strings:The primary string type isString(heap-allocated, growable) and
    string slices&str(a view into string data, often string literals).

5.3 Functions

Defined using the fn keyword. Type annotations for parameters and the return value are required.

fn add(x: i32, y: i32) -> i32 {
    // The last expression in a function is implicitly returned (no semicolon)
    x + y
    // Or explicitly return using the `return` keyword:
    // return x + y;
}

fn main() {
    let sum = add(5, 7);
    println!("Sum is: {}", sum); // Output: Sum is: 12
}

5.4 Comments

// This is a single-line comment.

/*
 * This is a
 * multi-line block comment.
 */

/// This is a documentation comment for the following item.
fn documented_function() {}

//! This is a documentation comment for the enclosing item (e.g., the module or crate).

5.5 Control Flow (if/else, loops)

let number = 6;

// if/else expressions
if number % 4 == 0 {
    println!("number is divisible by 4");
} else if number % 3 == 0 {
    println!("number is divisible by 3");
} else {
    println!("number is not divisible by 4 or 3");
}

// loop (infinite loop, break to exit)
let mut counter = 0;
loop {
    println!("Again!");
    counter += 1;
    if counter == 3 {
        break; // Exit the loop
    }
}

// while loop
let mut n = 3;
while n != 0 {
    println!("{}!", n);
    n -= 1;
}
println!("LIFTOFF!!!");

// for loop (iterating over a collection)
let a = [10, 20, 30, 40, 50];
for element in a {
    println!("the value is: {}", element);
}

// for loop with a range
for num in (1..4).rev() { // 3, 2, 1 (rev() reverses range)
    println!("{}!", num);
}

6. Next Steps

This guide covers the very basics. Key concepts to explore next in Rust include:

  • Ownership and Borrowing:Rust’s core memory management system.

  • Structs and Enums:Defining custom data structures.

  • Error Handling:UsingResultandpanic!.

  • Collections:Vectors (Vec), Hash Maps (HashMap), etc.

  • Traits:Rust’s approach to shared behavior (similar to interfaces).

  • Concurrency:Threads, message passing, async/await.

Additional Resources

Related Articles on InfoBytes.guru

External Resources