Rust is a powerful and modern programming language that emphasizes safety, performance, and concurrency. One of its key features is the module system, which allows developers to organize their code into logical units.
Modules in Rust are a fantastic way to organize your code into smaller, more manageable chunks. They allow you to group related code and data together, so you can keep your code clean and easy to understand.
Each module can have its own functions, types, and constants, which are only visible within that module. This is called “encapsulation,” and it helps to prevent errors and confusion in your code.
mod module1 {
pub fn function1() {
println!("function1 from module1");
}
}
mod module2 {
pub fn function2() {
println!("function2 from module2");
}
}
fn main() {
module1::function1();
module2::function2();
}
In this example, we have two modules, module1 and module2, each with a single public function. The main function calls both functions, demonstrating how to access functions from different modules.
In addition to promoting code organization and encapsulation, Rust modules can also enhance code reusability. Since each module is self-contained, you can easily reuse modules across different projects, reducing duplication and improving efficiency.
For a visual demonstration of how modules work, check out this video.
Understanding the Structure:
One thing that sets Rust modules apart is their tree-like structure. You can create submodules within modules, which helps you organize your code even more effectively. And the way they handle public and private items is really intuitive, with the default being private, so you don’t have to worry about accidentally exposing something you didn’t mean to.
Rust follows the principle of encapsulation by default, where items (functions, structs, etc.) are private unless explicitly marked as public. This approach ensures that only the necessary interfaces are exposed, reducing the risk of unintentional exposure of internal implementation details.
Let’s start by examining the structure of our Rust project. The main entry point is the main.rs file, and we have two modules named module1 and module2. The goal is to illustrate how modules help structure code in a meaningful way.
// Filename: src/main.rs
mod module1;
mod module2;
fn main() {
println!("Hello from main.rs!");
module1::run_module1();
module2::function2();
}
// Filename: src/module1.rs
pub fn run_module1() {
println!("Running module1.rs");
}
The main.rs file serves as the entry point for our Rust program. It uses the mod keyword to declare two modules: module1 and module2. These modules are then used within the `main` function to demonstrate how to call functions from different modules.
Tree-Like Structure and Visibility:
// src/main.rs
mod module1;
mod module2;
fn main() {
println!("Hello from main.rs!");
module1::run_module1();
module1::submodule::run_submodule(); // Accessing the submodule
module2::function2();
}
// src/module1.rs
pub fn run_module1() {
println!("Running module1.rs");
}
mod submodule; // submodule.rs is private by default
// src/module1/submodule.rs
pub fn run_submodule() {
println!("Running submodule.rs");
}
We have two modules, module1 and module2, which are declared at the top of the main.rs file using the mod keyword. Each module has its own functions, and in the main function, we call these functions to demonstrate how to access them from outside the module.
The module1 module contains a public function called run_module1, which simply prints a message to the console. It also has a submodule called submodule, which is declared using the mod keyword within the module1.rs file. The submodule contains a public function called run_submodule, which prints a message to the console.
In the main function, we call the run_module1 and run_submodule functions, as well as a function from the module2 module. This demonstrates how we can access functions from different modules, including those within submodules.
Further reading:
Rust Doc: https://doc.rust-lang.org/rust-by-example/mod.html