Related code and data are grouped into a module and stored in the same file.
fn main() {
greetings::hello();
}
mod greetings {
// ⭐️ By default, everything inside a module is private
pub fn hello() { // ⭐️ So function has to be public to access from outside
println!("Hello, world!");
}
}
Private functions can be called from the same module or from a child module.
// 01. Calling private functions of the same module
fn main() {
phrases::greet();
}
mod phrases {
pub fn greet() {
hello(); //or self::hello();
}
fn hello() {
println!("Hello, world!");
}
}
// 02. Calling private functions of the parent module
fn main() {
phrases::greetings::hello();
}
mod phrases {
fn private_fn() {
println!("Hello, world!");
}
pub mod greetings {
pub fn hello() {
super::private_fn();
}
}
}
💡 self keyword is used to refer same module, while super keyword is used to refer parent module. Also super keyword can be used to access root functions from inside a module.
🔎 When writing tests it’s a good practice to write tests inside a test module because of they compile only when running tests.
fn greet() -> String {
"Hello, world!".to_string()
}
#[cfg(test)] // only compiles when running tests
mod tests {
use super::greet; // import root greet function
#[test]
fn test_greet() {
assert_eq!("Hello, world!", greet());
}
}
02. In different file, same directory
// ↳ main.rs
mod greetings; // import greetings module
fn main() {
greetings::hello();
}
// ↳ greetings.rs
// ⭐️ no need to wrap the code with a mod declaration. File itself acts as a module.
pub fn hello() { // function has to be public to access from outside
println!("Hello, world!");
}
If we wrap file content with a mod declaration, it will act as a nested module.
// ↳ main.rs
mod phrases;
fn main() {
phrases::greetings::hello();
}
// ↳ phrases.rs
pub mod greetings { // ⭐️ module has to be public to access from outside
pub fn hello() {
println!("Hello, world!");
}
}
03. In different file, different directory
mod.rs in the directory module root is the entry point to the directory module. All other files in that directory root, act as sub-modules of the directory module.
// ↳ main.rs
mod greetings;
fn main() {
greetings::hello();
}
// ↳ greetings/mod.rs
pub fn hello() { // ⭐️ function has to be public to access from outside
println!("Hello, world!");
}
Again, If we wrap file content with a mod declaration, it will act as a nested module.
// ↳ main.rs
mod phrases;
fn main() {
phrases::greetings::hello();
}
// ↳ phrases/mod.rs
pub mod greetings { // ⭐️ module has to be public to access from outside
pub fn hello() {
println!("Hello, world!");
}
}
Other files in the directory module act as sub-modules for mod.rs.
🔎 It’s unable to import child file modules of directory modules to main.rs, so you can’t use mod phrases::greetings; from main.rs. But there is a way to import phrases::greetings::hello() to phrases module by re-exporting hello to phrases module. So you can call it directly as phrases::hello().
// ↳ phrases/greetings.rs
pub fn hello() {
println!("Hello, world!");
}
// ↳ phrases/mod.rs
pub mod greetings;
pub use self::greetings::hello; //re-export greetings::hello to phrases
// ↳ main.rs
mod phrases;
fn main() {
phrases::hello(); //you can call hello() directly from phrases
}
This allows you to present an external interface that may not directly map to your internal code organization. If still it is not clear, don’t worry; We discuss the usages of use on an upcoming section in this post.