Related code and data are grouped into a module and stored in the same file.
fnmain() { greetings::hello();}mod greetings {// ⭐️ By default, everything inside a module is privatepubfnhello() { // ⭐️ So function has to be public to access from outsideprintln!("Hello, world!"); }}
Private functions can be called from the same module or from a child module.
// 01. Calling private functions of the same modulefnmain() { phrases::greet();}mod phrases {pubfngreet() {hello(); //or self::hello(); }fnhello() {println!("Hello, world!"); }}// 02. Calling private functions of the parent modulefnmain() { phrases::greetings::hello();}mod phrases {fnprivate_fn() {println!("Hello, world!"); }pubmod greetings {pubfnhello() { 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.
fngreet() ->String {"Hello, world!".to_string()}#[cfg(test)] // only compiles when running testsmod tests {use super::greet; // import root greet function #[test]fntest_greet() {assert_eq!("Hello, world!", greet()); }}
02. In different file, same directory
// ↳ main.rsmod greetings; // import greetings modulefnmain() { greetings::hello();}// ↳ greetings.rs// ⭐️ no need to wrap the code with a mod declaration. File itself acts as a module.pubfnhello() { // function has to be public to access from outsideprintln!("Hello, world!");}
If we wrap file content with a mod declaration, it will act as a nested module.
// ↳ main.rsmod phrases;fnmain() { phrases::greetings::hello();}// ↳ phrases.rspubmod greetings { // ⭐️ module has to be public to access from outsidepubfnhello() {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.rsmod greetings;fnmain() { greetings::hello();}// ↳ greetings/mod.rspubfnhello() { // ⭐️ function has to be public to access from outsideprintln!("Hello, world!");}
Again, If we wrap file content with a mod declaration, it will act as a nested module.
// ↳ main.rsmod phrases;fnmain() { phrases::greetings::hello();}// ↳ phrases/mod.rspubmod greetings { // ⭐️ module has to be public to access from outsidepubfnhello() {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.rspubfnhello() {println!("Hello, world!");}// ↳ phrases/mod.rspubmod greetings;pubuse self::greetings::hello; //re-export greetings::hello to phrases// ↳ main.rsmod phrases;fnmain() { 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.