0
0
Rustprogramming~15 mins

Program structure in Rust - Deep Dive

Choose your learning style9 modes available
Overview - Program structure in Rust
What is it?
Program structure in Rust is how you organize your code so the computer understands what to do. It includes parts like functions, modules, and the main entry point where the program starts running. Rust programs are made of small pieces that work together clearly and safely. This structure helps keep code neat and easy to follow.
Why it matters
Without a clear program structure, code becomes messy and hard to fix or improve. Rust's structure helps prevent bugs and makes programs run efficiently. It guides you to write safe and fast code that others can read and build upon. This is important because software often grows bigger and more complex over time.
Where it fits
Before learning Rust program structure, you should know basic programming ideas like variables and functions. After this, you can learn about Rust's ownership rules, error handling, and advanced module systems. Understanding program structure is a foundation for writing any Rust application.
Mental Model
Core Idea
A Rust program is a set of organized pieces—functions and modules—starting from a main function that tells the computer where to begin.
Think of it like...
Think of a Rust program like a recipe book: the main function is the first recipe you follow, and modules are chapters grouping related recipes together, making it easy to find and use what you need.
┌───────────────┐
│   Program     │
│  Structure    │
└──────┬────────┘
       │
       ▼
┌───────────────┐
│   main()      │  <-- Program starts here
└──────┬────────┘
       │
       ▼
┌───────────────┐      ┌───────────────┐
│  Modules      │─────▶│ Functions     │
│ (group code)  │      │ (do tasks)    │
└───────────────┘      └───────────────┘
Build-Up - 7 Steps
1
FoundationUnderstanding the main function
🤔
Concept: The main function is where a Rust program starts running.
Every Rust program needs a main function. It looks like this: fn main() { println!("Hello, world!"); } This tells the computer to print a message when the program runs.
Result
When you run this program, it prints: Hello, world!
Knowing that main() is the starting point helps you organize what your program does first.
2
FoundationBasic functions for tasks
🤔
Concept: Functions let you break your program into smaller, reusable pieces.
You can write functions to do specific jobs: fn greet() { println!("Hi there!"); } fn main() { greet(); } Here, main calls greet to say hello.
Result
Running this prints: Hi there!
Functions help keep code clean and let you reuse actions without repeating code.
3
IntermediateOrganizing code with modules
🤔Before reading on: do you think modules are just folders or do they also affect how code runs? Commit to your answer.
Concept: Modules group related functions and data to keep code organized and avoid name conflicts.
Modules are declared with the mod keyword: mod greetings { pub fn hello() { println!("Hello from module!"); } } fn main() { greetings::hello(); } The pub keyword makes hello() usable outside the module.
Result
The program prints: Hello from module!
Understanding modules helps you build bigger programs by grouping code logically and controlling what is visible outside.
4
IntermediateUsing external files for modules
🤔Before reading on: do you think modules must be inside the main file or can they be in separate files? Commit to your answer.
Concept: Modules can be placed in separate files to keep code clean and manageable.
If you have a file greetings.rs with: pub fn hello() { println!("Hello from file module!"); } Then in main.rs: mod greetings; fn main() { greetings::hello(); } Rust automatically links the file as a module.
Result
Running prints: Hello from file module!
Splitting modules into files helps manage large projects and makes code easier to navigate.
5
IntermediateVisibility and privacy rules
🤔
Concept: Rust controls what parts of modules are visible outside using pub and private by default.
By default, functions and variables inside modules are private: mod secret { fn hidden() { println!("You can't see me!"); } } fn main() { // secret::hidden(); // This would cause an error } Making a function pub allows access from outside.
Result
Trying to call a private function from outside causes a compile error.
Visibility rules protect your code from accidental misuse and help maintain clear interfaces.
6
AdvancedCrate and package structure basics
🤔Before reading on: do you think a crate is just a module or something bigger? Commit to your answer.
Concept: A crate is the smallest unit of Rust code compilation and can be a binary or library package.
When you create a Rust project with Cargo, it builds a crate. - Binary crate: produces an executable with main() - Library crate: provides reusable code without main() Crates can contain many modules and files organized inside src/.
Result
Understanding crates helps you manage dependencies and build projects correctly.
Knowing crates clarifies how Rust compiles and packages code, which is key for larger projects and sharing code.
7
ExpertModule system internals and path resolution
🤔Before reading on: do you think Rust resolves module paths only by file names or also by code declarations? Commit to your answer.
Concept: Rust uses a set of rules to find modules by combining file system layout and mod declarations, resolving paths at compile time.
Rust looks for modules in files or folders matching the mod name: - mod foo; looks for foo.rs or foo/mod.rs - Nested modules follow folder structure Paths like crate::module::function refer to the root crate and nested modules. This system ensures clear, predictable code organization.
Result
Correct module resolution avoids compile errors and keeps code maintainable.
Understanding path resolution prevents confusing errors and helps design scalable module hierarchies.
Under the Hood
Rust compiles code by starting at the main function in the root crate. It uses mod declarations to include modules, which the compiler finds in files or folders. Each module creates a namespace to avoid name clashes. The compiler enforces visibility rules at compile time, so private items cannot be accessed outside their module. This structure allows Rust to check code safety and correctness before running.
Why designed this way?
Rust's program structure was designed to combine safety, clarity, and performance. The module system is inspired by other languages but enforces strict visibility to prevent bugs. Using a crate system allows easy code sharing and dependency management. The design balances flexibility with strict rules to help programmers write reliable software.
┌───────────────┐
│   Cargo.toml  │  <-- Project config and dependencies
└──────┬────────┘
       │
┌──────▼───────┐
│   src/       │  <-- Source folder
│ ┌─────────┐  │
│ │main.rs  │  │  <-- Root crate with main()
│ └─────────┘  │
│ ┌─────────┐  │
│ │foo.rs   │  │  <-- Module file
│ └─────────┘  │
└──────────────┘

Compiler flow:
main.rs (mod foo;) --> foo.rs

Visibility:
[private] items hidden inside modules
[pub] items accessible outside
Myth Busters - 4 Common Misconceptions
Quick: Do you think all functions in Rust are public by default? Commit to yes or no.
Common Belief:All functions you write are public and can be used anywhere.
Tap to reveal reality
Reality:Functions are private by default and only accessible inside their module unless marked pub.
Why it matters:Assuming functions are public leads to compile errors when trying to use them outside their module.
Quick: Do you think the main function can be named anything else? Commit to yes or no.
Common Belief:You can name the starting function anything you want.
Tap to reveal reality
Reality:The program always starts at a function named main with no parameters and no return value.
Why it matters:Naming the entry point differently causes the program not to run, confusing beginners.
Quick: Do you think modules must always be in separate files? Commit to yes or no.
Common Belief:Modules must be in their own files to work.
Tap to reveal reality
Reality:Modules can be declared inside the same file or in separate files; both ways are valid.
Why it matters:Believing modules require separate files can make beginners overcomplicate small programs.
Quick: Do you think crates and modules are the same thing? Commit to yes or no.
Common Belief:A crate is just another name for a module.
Tap to reveal reality
Reality:A crate is a complete package or binary, while modules are parts inside a crate.
Why it matters:Confusing crates and modules leads to misunderstanding project structure and dependency management.
Expert Zone
1
Modules can be nested deeply, but excessive nesting can hurt readability and should be balanced.
2
The pub(crate) visibility modifier allows making items visible only within the current crate, a subtle but powerful access control.
3
Rust's module system supports conditional compilation with attributes like #[cfg], enabling platform-specific code organization.
When NOT to use
For very small scripts or one-off programs, complex module structures may be unnecessary overhead. Instead, simple flat files or single-file programs suffice. Also, when rapid prototyping, strict module boundaries can slow down iteration. Alternatives include scripting languages or minimal Rust programs without modules.
Production Patterns
In real-world Rust projects, modules are organized by feature or domain, with clear public APIs exposed via pub. Crates are used to package libraries for reuse. Cargo manages dependencies and builds. Large projects use workspace crates to group related crates. Visibility modifiers control internal vs external access, enforcing encapsulation.
Connections
Namespaces in C++
Rust modules serve a similar purpose to C++ namespaces by grouping code and avoiding name conflicts.
Understanding Rust modules helps grasp how different languages organize code to prevent clashes and improve clarity.
Package management in Node.js (npm)
Rust crates and Cargo are analogous to npm packages and package.json, managing dependencies and project structure.
Knowing Rust crates clarifies how modern languages handle code sharing and versioning across projects.
Library organization in a physical library
Modules and crates organize code like sections and shelves organize books in a library for easy finding and use.
This connection shows how organizing information efficiently is a universal challenge across fields.
Common Pitfalls
#1Trying to call a private function from outside its module.
Wrong approach:mod math { fn add(a: i32, b: i32) -> i32 { a + b } } fn main() { let sum = math::add(2, 3); println!("Sum is {}", sum); }
Correct approach:mod math { pub fn add(a: i32, b: i32) -> i32 { a + b } } fn main() { let sum = math::add(2, 3); println!("Sum is {}", sum); }
Root cause:Not marking functions as pub means they are private and inaccessible outside their module.
#2Naming the entry function something other than main.
Wrong approach:fn start() { println!("Hello"); } // No main function
Correct approach:fn main() { println!("Hello"); }
Root cause:Rust requires a main function as the program entry point; other names are ignored.
#3Declaring a module but forgetting to link the file.
Wrong approach:// In main.rs mod utils; fn main() { utils::help(); } // No utils.rs file present
Correct approach:// Create utils.rs with: // pub fn help() { // println!("Helping"); // } // In main.rs mod utils; fn main() { utils::help(); }
Root cause:Rust expects module files to exist when declared; missing files cause compile errors.
Key Takeaways
Every Rust program starts execution from a special function named main with no parameters.
Functions break code into reusable pieces, and modules group related functions to keep code organized.
Modules control visibility with pub, making some parts accessible outside while keeping others private.
Crates are the building blocks of Rust projects, packaging code for compilation and reuse.
Understanding Rust's module and crate system is essential for writing clear, maintainable, and scalable programs.