5/5
## Understanding Your First Rust Program: `main`, Attributes, and `println!` Welcome! In this lesson, we'll dissect the fundamental components of a simple Rust program and explore how we'll structure and run code examples throughout this course. We'll build upon a basic "Hello, world!" project, focusing on the `main` function, an important Rust feature called attributes, and the commonly used `println!` macro. ### Organizing Your Rust Code: Introducing the `examples` Folder Previously, we set up a Rust project named `hello_rust` using Cargo. This project initialized with a `src` directory containing a `main.rs` file. Initially, our `src/main.rs` looked something like this, designed to print "Hello, world!" three times: ```rust // In src/main.rs (initial state) fn main() { println!("Hello, world!"); println!("Hello, world!"); println!("Hello, world!"); } ``` Throughout this course, we'll be working with numerous small, executable Rust code snippets to illustrate various concepts. Instead of modifying our main `src/main.rs` file each time, we'll leverage a special folder recognized by Cargo: the `examples` folder. You can create an `examples` folder at the root of your Rust project (e.g., `hello_rust/examples/`). Any Rust source file (with a `.rs` extension) placed directly within this `examples` folder that contains a `fn main()` function will be automatically recognized by Cargo as a separate, compilable, and runnable program. This is incredibly useful for managing multiple distinct demonstrations within a single project. ### Crafting Your First Example: `hello.rs` Let's put this into practice. First, create a new folder named `examples` at the root level of your `hello_rust` project. Inside this `hello_rust/examples/` directory, create a new file named `hello.rs`. Now, copy the content from your existing `src/main.rs` file into this new `examples/hello.rs`. For our first example, we'll simplify it to print "Hello, world!" just once and remove any initial comments. The content of `examples/hello.rs` will now be: ```rust // In examples/hello.rs fn main() { println!("Hello, world!"); } ``` ### Understanding Rust Attributes: `#![allow(unused)]` As we build our examples, you'll often see a specific line at the very top of our `.rs` files: ```rust #![allow(unused)] ``` This line introduces a Rust concept called **attributes**. Attributes are metadata that you provide to the Rust compiler, influencing its behavior or providing information about your code. Let's break down this specific attribute: * The `#` symbol followed by an exclamation mark `!` and square brackets `#![...]` signifies an **inner attribute**. When placed at the beginning of a file, it applies to the entire crate or module (in this case, the entire `hello.rs` file). * `allow(unused)` is the attribute itself. It instructs the Rust compiler to suppress warnings that would normally be generated for things like unused variables, functions, or imports. Why use this? In production-level projects, these "unused" warnings are very valuable, helping you identify and remove dead code. However, for small, focused educational examples, these warnings can sometimes be distracting or clutter the output when we're trying to demonstrate a specific feature. By using `#![allow(unused)]`, we keep our example code cleaner and our focus tighter. Let's add this attribute to the top of our `examples/hello.rs` file: ```rust // In examples/hello.rs #![allow(unused)] // Attribute: metadata for the compiler fn main() { println!("Hello, world!"); } ``` ### The Heart of Your Program: The `fn main()` Function The line `fn main()` declares a function named `main`. In Rust, the `main` function is special: it serves as the **entry point** for any executable program. When you run a compiled Rust program, the code within the `main` function is the very first code that gets executed. Every Rust binary executable must have a `main` function. We can add a comment to our `examples/hello.rs` to highlight this: ```rust // In examples/hello.rs #![allow(unused)] // main() is the entry point of a Rust program fn main() { println!("Hello, world!"); } ``` ### Running Your Examples with Cargo Typically, when you execute the command `cargo run` in your project's root directory, Cargo compiles and runs the binary generated from `src/main.rs`. However, to run one of the programs from our `examples` folder, we need to tell Cargo specifically which example we intend to run. This is done using the `--example` flag: ```bash cargo run --example <example_name> ``` Here, `<example_name>` corresponds to the filename of your example in the `examples` folder, but *without* the `.rs` extension. Let's try this. If you run `cargo run` (without any flags) in your `hello_rust` project, it will still execute `src/main.rs` (which, if you haven't changed it, prints "Hello, world!" three times). Now, execute the following command: ```bash cargo run --example hello ``` You'll see output similar to this: ``` Compiling hello_rust v0.1.0 (/path/to/your/hello_rust) Finished dev [unoptimized + debuginfo] target(s) in Xs Running `target/debug/examples/hello` Hello, world! ``` As you can see, Cargo compiled and ran `examples/hello.rs`, and our single "Hello, world!" message was printed to the console. ### Unveiling Rust Macros: The Power of `println!` Let's look closely at the line `println!("Hello, world!");`. It might look like a regular function call, but there's a key syntactic difference: the exclamation mark (`!`) at the end of `println`. This `!` signifies that `println!` is not a function, but a **macro**. What's the difference? Macros in Rust are a powerful feature for meta-programming; they are essentially code that writes other code. When the Rust compiler encounters a macro invocation (like `println!`), it expands the macro into actual Rust code *before* the main compilation process begins. The `println!` macro, specifically, is a standard Rust macro designed to print text to the standard output (your console). It handles formatting the string you provide (and any additional arguments, which we'll see later) and appends a newline character at the end, so subsequent output starts on a new line. Let's update `examples/hello.rs` with comments explaining macros: ```rust // In examples/hello.rs #![allow(unused)] // main() is the entry point of a Rust program // Macros in Rust generate code at compile time and are // invoked with an exclamation mark (!). fn main() { // println! is a macro that prints text to the console. println!("Hello, world!"); } ``` ### Core Rust Concepts: A Quick Review In this lesson, we've covered several foundational Rust elements: * **Attributes (`#![allow(unused)]`)**: These provide metadata to the compiler. `allow(unused)` is an attribute that tells the compiler to suppress warnings for unused code elements, which is useful for keeping educational examples concise. * **`fn main()`**: This function is the designated entry point for all Rust executable programs. Execution begins here. * **Macros (e.g., `println!`)**: Invoked with an exclamation mark (`!`), macros are a form of compile-time code generation. `println!` is a standard macro used to print formatted text to the console, followed by a newline. * **Running Examples**: To compile and run a specific program from the `examples/` directory, use the command `cargo run --example <binary_name>`, where `<binary_name>` is the filename without the `.rs` extension (e.g., `hello` for `hello.rs`). Understanding these components—project structure with `examples`, the role of `fn main()`, the utility of attributes like `#![allow(unused)]`, and the nature of macros like `println!`—will provide a solid foundation as we delve deeper into Rust programming.
main
, Attributes, and println!
Welcome! In this lesson, we'll dissect the fundamental components of a simple Rust program and explore how we'll structure and run code examples throughout this course. We'll build upon a basic "Hello, world!" project, focusing on the main
function, an important Rust feature called attributes, and the commonly used println!
macro.
examples
FolderPreviously, we set up a Rust project named hello_rust
using Cargo. This project initialized with a src
directory containing a main.rs
file. Initially, our src/main.rs
looked something like this, designed to print "Hello, world!" three times:
Throughout this course, we'll be working with numerous small, executable Rust code snippets to illustrate various concepts. Instead of modifying our main src/main.rs
file each time, we'll leverage a special folder recognized by Cargo: the examples
folder.
You can create an examples
folder at the root of your Rust project (e.g., hello_rust/examples/
). Any Rust source file (with a .rs
extension) placed directly within this examples
folder that contains a fn main()
function will be automatically recognized by Cargo as a separate, compilable, and runnable program. This is incredibly useful for managing multiple distinct demonstrations within a single project.
hello.rs
Let's put this into practice. First, create a new folder named examples
at the root level of your hello_rust
project. Inside this hello_rust/examples/
directory, create a new file named hello.rs
.
Now, copy the content from your existing src/main.rs
file into this new examples/hello.rs
. For our first example, we'll simplify it to print "Hello, world!" just once and remove any initial comments.
The content of examples/hello.rs
will now be:
#![allow(unused)]
As we build our examples, you'll often see a specific line at the very top of our .rs
files:
This line introduces a Rust concept called attributes. Attributes are metadata that you provide to the Rust compiler, influencing its behavior or providing information about your code.
Let's break down this specific attribute:
The #
symbol followed by an exclamation mark !
and square brackets #![...]
signifies an inner attribute. When placed at the beginning of a file, it applies to the entire crate or module (in this case, the entire hello.rs
file).
allow(unused)
is the attribute itself. It instructs the Rust compiler to suppress warnings that would normally be generated for things like unused variables, functions, or imports.
Why use this? In production-level projects, these "unused" warnings are very valuable, helping you identify and remove dead code. However, for small, focused educational examples, these warnings can sometimes be distracting or clutter the output when we're trying to demonstrate a specific feature. By using #![allow(unused)]
, we keep our example code cleaner and our focus tighter.
Let's add this attribute to the top of our examples/hello.rs
file:
fn main()
FunctionThe line fn main()
declares a function named main
. In Rust, the main
function is special: it serves as the entry point for any executable program. When you run a compiled Rust program, the code within the main
function is the very first code that gets executed. Every Rust binary executable must have a main
function.
We can add a comment to our examples/hello.rs
to highlight this:
Typically, when you execute the command cargo run
in your project's root directory, Cargo compiles and runs the binary generated from src/main.rs
.
However, to run one of the programs from our examples
folder, we need to tell Cargo specifically which example we intend to run. This is done using the --example
flag:
Here, <example_name>
corresponds to the filename of your example in the examples
folder, but without the .rs
extension.
Let's try this. If you run cargo run
(without any flags) in your hello_rust
project, it will still execute src/main.rs
(which, if you haven't changed it, prints "Hello, world!" three times).
Now, execute the following command:
You'll see output similar to this:
As you can see, Cargo compiled and ran examples/hello.rs
, and our single "Hello, world!" message was printed to the console.
println!
Let's look closely at the line println!("Hello, world!");
. It might look like a regular function call, but there's a key syntactic difference: the exclamation mark (!
) at the end of println
. This !
signifies that println!
is not a function, but a macro.
What's the difference? Macros in Rust are a powerful feature for meta-programming; they are essentially code that writes other code. When the Rust compiler encounters a macro invocation (like println!
), it expands the macro into actual Rust code before the main compilation process begins.
The println!
macro, specifically, is a standard Rust macro designed to print text to the standard output (your console). It handles formatting the string you provide (and any additional arguments, which we'll see later) and appends a newline character at the end, so subsequent output starts on a new line.
Let's update examples/hello.rs
with comments explaining macros:
In this lesson, we've covered several foundational Rust elements:
Attributes (#![allow(unused)]
): These provide metadata to the compiler. allow(unused)
is an attribute that tells the compiler to suppress warnings for unused code elements, which is useful for keeping educational examples concise.
fn main()
: This function is the designated entry point for all Rust executable programs. Execution begins here.
Macros (e.g., println!
): Invoked with an exclamation mark (!
), macros are a form of compile-time code generation. println!
is a standard macro used to print formatted text to the console, followed by a newline.
Running Examples: To compile and run a specific program from the examples/
directory, use the command cargo run --example <binary_name>
, where <binary_name>
is the filename without the .rs
extension (e.g., hello
for hello.rs
).
Understanding these components—project structure with examples
, the role of fn main()
, the utility of attributes like #![allow(unused)]
, and the nature of macros like println!
—will provide a solid foundation as we delve deeper into Rust programming.
An illuminating walkthrough of Understanding Your First Rust Program: `main`, Attributes, and `println!` - Uncover the significance of the `main` function, the role of compiler attributes like `#![allow(unused)]`, and the power of the `println!` macro for output. You'll also get hands-on with organizing and running separate Rust snippets via Cargo's `examples` directory.
Previous lesson
Previous
Next lesson
Next
Give us feedback
Course Overview
About the course
Introduction to the Rust programming language
Rust variables and functions
Scalar types, arrays, strings, enum, structs, vectors, and hash maps in Rust
Rust control flows: If / else, if let and let else, loop, match
Rust ownership, including borrow and references
Rust error handling
Rust Modules
Rust Traits
Last updated on July 11, 2025
Rust Developer
Rust Programming BasicsDuration: 6min
Duration: 18min
Duration: 47min
Duration: 15min
Duration: 19min
Duration: 8min
Duration: 12min
Duration: 46min
Duration: 14min
Course Overview
About the course
Introduction to the Rust programming language
Rust variables and functions
Scalar types, arrays, strings, enum, structs, vectors, and hash maps in Rust
Rust control flows: If / else, if let and let else, loop, match
Rust ownership, including borrow and references
Rust error handling
Rust Modules
Rust Traits
Last updated on July 11, 2025