This article is intended for beginners of Rust to help you understand how rust modules refer to each other. This article uses as little code as possible to demonstrate that rust is familiar even if you haven’t seen it before. It gives you an impression when you use it.

If you haven’t seen rust before, just know this: Cargo- dependency management tool. Similar to NPM, Cargo uses a file placement convention where the file name is the module name. Crate – container, which is a package with a set of features, similar to an NPM package.

Scenario is explored in the project to different levels of code file splitting and module pull away, often need to introduce another module into a file of the part of the code, in javascript, we can use other module code through import and export, we only need to care about the process to import the path is correct.

export const name= xx 
import lodash from './lodash'
Copy the code

In Rust, modules are no longer imported through a file path, but rather through cargo and the convention of module declarations to build a module tree, which is then used through the use keyword. Rust’s documentation on file splitting and module use is less detailed, so it’s combed through with reference to some of the crate’s organization.

Module declaration & use

Suppose we want to implement an addition module and make it available elsewhere. We can organize ourselves in three ways

Cargo uses a file placement convention, so modules look up RS files or directories in the SRC directory and only look up one level. Rs files in nested folders cannot be used by other files directly.

Method 1: Declare directly in the root file add.rs

Cargo can identify the Add module by adding a file with the same module name under SRC.

├ ─ ─ Cargo. Lock ├ ─ ─ Cargo. Toml ├ ─ ─ the SRC │ ├ ─ ─ the add. Rs │ ├ ─ ─ lib. RsCopy the code

Method 2: declare the add folder, folder contains mod.rs

If the module is a folder, you must have the mod.rs file. This is similar to javascript’s index.js. Cargo still recognizes that this is the ADD module

├ ─ ─ Cargo. Lock ├ ─ ─ Cargo. Toml ├ ─ ─ the SRC │ ├ ─ ─ the add │ │ ├ ─ ─ mod. Rs │ ├ ─ ─ lib. RsCopy the code

Suppose our code looks like this and is in the file Add.rs or Add /mod.rs

pub fn add_fn(a: i32, b: i32) -> i32 {
    a + b
}
Copy the code

So in lib.rs we can call our add module as follows

// Declare the module and reference the module function mod add; pub use crate::add::add_fn; Pub fn test_lib() {add_fn(1,2); }Copy the code

Method 3: Add. Rs and add folders exist at the same time

The directory structure in this way looks like this

├ ─ ─ Cargo. Lock ├ ─ ─ Cargo. Toml ├ ─ ─ the SRC │ ├ ─ ─ the add │ │ └ ─ ─ add_m. Rs │ ├ ─ ─ the add. The rs / / index. The js │ ├ ─ ─ lib. RsCopy the code

Rs is responsible for import and export of the entry module, and other related modules are stored in the add folder. This is similar to javascript’s index.js exporting multiple other modules uniformly. The difference is that the import uses the mod keyword to split the module;

The file contents look like this

add.rs

pub mod add_m; Export * from './validate; export * from './helper'Copy the code

add/add_m.rs

pub fn add_fn(a: i32, b: i32) -> i32 {
    a + b
}
Copy the code

lib.rs

mod add; pub use crate::add::add_m::add_fn; Pub fn test_lib() {add_fn(1,2); }Copy the code

The first two of the above three methods should be used more often, and the second is more reasonable in large projects and can better organize documents. How to call adjacent files when splitting multiple module files in a module folder?

References to adjacent files of the same module

Let’s adjust the directory structure as follows

├ ─ ─ Cargo. Lock ├ ─ ─ Cargo. Toml ├ ─ ─ the SRC │ ├ ─ ─ the add │ │ ├ ─ ─ mod. Rs │ │ ├ ─ ─ print. Rs │ │ └ ─ ─ the user. The rs / / user will call the print method │ ├ ─ ─  lib.rsCopy the code

Print and User are added under add module. The user calls the method of print.

print.rs

pub mod my_print { pub fn print_hello() { println! (hello)}} // The pub mod is the TS Declare Module // declare Module my_print {export function print_hello(): string; // declare module my_print {export function print_hello(): string; / /}Copy the code

user.rs

use super::print::my_print;

pub fn hello_user() {
    my_print::print_hello();
}
pub struct User {
    pub name: String,
}
Copy the code

Cross-reference files under the same module using the super keyword.

mod.rs

Rs is the entry file, the following mod declaration will first look for files with the same name in the same folder, if not, then check whether there is a folder with the same name that meets the conditions // for example, if there is no print. mod print; mod user; Self pub use self::user::hello_user; pub use self::user::User; pub mod add_fn { // use super::*; Instead of calling super pub fn add(a: i32, b: I32) -> i32 {// Notice the super keyword here, since hello_user is declared in another module and cannot be called directly between modules, we need to use super to look up from the module root. let value = super::User { name: String::from( Rust ), }; println! ( user name {} , value.name); A + b}} pub fn test_out_ref() {super is not needed because hello_user() is not defined in the mod; }Copy the code

Different module references

We added a new module, multip, that returns the result of multiplying two numbers, with the following directory structure

├ ─ ─ Cargo. Lock ├ ─ ─ Cargo. Toml ├ ─ ─ the SRC │ ├ ─ ─ the add │ │ ├ ─ ─ mod. Rs │ │ ├ ─ ─ print. Rs │ │ └ ─ ─ the user. The rs / / user will call the print method │ ├ ─ ─ Multip / / -- -- -- -- -- -- -- new this module │ │ ├ ─ ─ mod. Rs method │ ├ ─ ─ lib. RsCopy the code

multip/mod.rs

pub fn res_multip(a: i32, b: i32) -> i32 {
    a * b
}
Copy the code

Suppose the add file introduces multip

mod print; mod user; pub use self::user::hello_user; pub use self::user::User; Use crate::multi::multip;Copy the code

This allows you to use the contents of another module. Of course, other modules reference each other in the same way.

summary

In general, the use of rust modules is relatively simple. Since the official documentation does not provide a complete description of module splitting and organization, students who have just switched to RUST from JS may find it a little uncomfortable. Through the previous content has been more clear combing the use of the way. I hope it can help students in need.