8.1 The main Function: The Program’s Entry Point

Every executable Rust program must contain exactly one function named main. This function serves as the starting point when the compiled binary is executed.

fn main() {
    println!("Hello from the main function!");
}

Key characteristics of main:

  • Parameters: By default, main takes no parameters. To access command-line arguments passed to the program, you use the std::env::args() function, which returns an iterator over the arguments.
  • Return Type: The main function typically returns the unit type (), signifying no specific value is returned (similar to void in C functions that don’t return a value). Alternatively, main can return a Result<(), E> where E is some error type that implements std::process::Termination. This is particularly useful for propagating errors encountered during program execution, often used in conjunction with the ? operator for concise error handling.

8.1.1 Accessing Command-Line Arguments

You can collect command-line arguments into a Vec<String> using std::env::args():

use std::env;

fn main() {
    // The first argument (args[0]) is typically the path to the executable itself.
    let args: Vec<String> = env::args().collect();
    println!("Program path: {}", args.get(0).unwrap_or(&"Unknown".to_string()));
    println!("Arguments passed: {:?}", &args[1..]);
    // Example: Check for a specific argument
    if args.len() > 1 && args[1] == "--help" {
        println!("Displaying help information...");
        // ... logic to display help ...
    }
}

8.1.2 Returning a Result from main

Returning Result from main provides a standard way to indicate whether the program executed successfully (Ok(())) or encountered an error (Err(E)). If main returns an Err, Rust will typically print the error description to standard error and exit with a non-zero status code.

use std::fs::File;
use std::io;

// main returns a Result to indicate success or failure (specifically I/O errors).
fn main() -> Result<(), io::Error> {
    // Attempt to open a file that might not exist.
    let _f = File::open("non_existent_file.txt")?;
    // The '?' operator propagates the error if File::open fails.
    println!("File opened successfully (this won't print if the file doesn't exist).");
    // If everything succeeded, return Ok.
    Ok(())
}

This pattern simplifies error handling at the top level of your application.