Rust’s code organization can be divided into functions, modules, Crate, and Workspace. Workspace manages different Grates, crate manages different mods, and mod manages different functions.
function
A function is the smallest unit of organization code. For example:
fn main() { greet(); //do one thing ask_location(); //do another thing } fn greet() { println! ("Hello!" ); } fn ask_location() { println! ("Where are you from?" ); }Copy the code
Add unit tests for functions in the same file
#[test] fn test_greet() { assert_eq! ("Hello, world!" , greet()) }Copy the code
The #[test] attribute indicates that the function is a unit test.
mod
The mod and the code are in the same file
fn main(){ greetings::hello(); } mod greetings { pub fn hello() { println! ("Hello world !" ); }}Copy the code
Nested mod
fn main(){
phrases::greetints::hello();
}
mod phrases {
pub mod greetings {
pub fn hello(){
println!("Hello, world!");
}
}
}Copy the code
Private functions can be called in the same mod or submod
fn main() { phrases::greet(); } mod phrases { pub fn greet() { hello(); //or self::hello(); } fn hello() { println! ("Hello, world!" ); } } fn main() { phrases::greetings::hello(); } mod phrases { fn private_fn() { println! ("Hello, world!" ); } pub mod greetings { pub fn hello() { super::private_fn(); }}}Copy the code
In the above program, self represents the current mod and super represents the parent mod.
Split the mod into different files under the same path
// main.rs mod greetings; // import greetings module fn main() { greetings::hello(); } // greetings. Rs // No need to display declaration mod, default is the filename as the mod name pub fn hello() {println! ("Hello, world!" ); }Copy the code
If a mod file is wrapped with the mod keyword:
// ↳ main.rs mod phrases; fn main() { phrases::greetings::hello(); } // ↳ phrases.rs pub mod greetings {pub fn hello() {println! ("Hello, world!" ); }}Copy the code
The mod is scattered to different files in different paths
Mod. rs is the entry file of a mod in the real path, and all files in the same path are its submods.
// ↳ main.rs mod greetings; fn main() { greetings::hello(); } // ↳ greetings/mod.rs pub fn hello() {println! ("Hello, world!" ); }Copy the code
Put it in a different file
// ↳ main.rs mod phrases; fn main() { phrases::greetings::hello(); } // ↳ phrases/mod.rs pub mod greetings; // ↳ phrases/greetings. Rs pub fn hello() {println! ("Hello, world!" ); }Copy the code
crate
Lib. rs and the executable are in the same Crate
When writing executables, you can put other functions in SRC /lib.rs and reference them in SRC /main.rs
cargo new --bin greetings
touch greetings/src/lib.rsCopy the code
// 01. greetings/src/lib.rs pub fn hello() { println! ("Hello, world!" ); } // 02. greetings/src/main.rs extern crate greetings; fn main() { greetings::hello(); }Copy the code
The lib.rs file references other files
cargo new --bin phrases touch phrases/src/lib.rs touch phrases/src/greetings.rs // # Think we modify following files // 01. phrases/src/greetings.rs pub fn hello() { println! ("Hello, world!" ); } // 02. phrases/src/main.rs extern crate phrases; fn main() { phrases::greetings::hello(); } // 03. phrases/src/lib.rs pub mod greetings;Copy the code
Declare dependencies in Cargo. Toml
Dependency based on file path:
[package] name = "phrases" version = "0.1.0" authors = ["Dumindu Rajarathna"] [dependencies] greetings = {path = "greetings" } // 02. phrases/greetings/src/lib.rs pub fn hello() { println! ("Hello, world!" ); } // 03. phrases/src/main.rs extern crate greetings; fn main() { greetings::hello(); }Copy the code
Git based dependencies:
// -- Cargo.toml -- [dependencies] rocket = { git = "https://github.com/SergioBenitez/Rocket" } rocket = { git = "https://github.com/SergioBenitez/Rocket", Branch = "v0.3"} rocket = {git = "https://github.com/SergioBenitez/Rocket", Tag = "v0.3.2}" rocket = {git = "https://github.com/SergioBenitez/Rocket", rev = "8183f636305cef4adaa9525506c33cbea72d1745" }Copy the code
Based on the crates. IO version
[dependencies] test_crate_hello_world = "0.1.0 from"Copy the code
workspace
As code volumes grow, a project may contain multiple Grates, which Rust supports through workspace.
// # Think we run mkdir greetings touch greetings/Cargo.toml cargo new greetings/lib cargo new --bin greetings/examples/hello // # That generates, . ├ ─ ─ Cargo. Toml ├ ─ ─ examples │ └ ─ ─ the hello │ ├ ─ ─ Cargo. Toml │ └ ─ ─ the SRC │ └ ─ ─ main. Rs └ ─ ─ lib ├ ─ ─ Cargo. Toml └ ─ ─ the SRC └ ─ ─ lib.rs // # Think we modify following files // 01. greetings/Cargo.toml [workspace] members = [ "lib", "Examples /hello"] // 02.1 greetings/lib/Cargo. Toml [package] name = "greetings" version = "0.1.0" authors = ["Dumindu Madunuwan"] [dependencies] // 02.2 greetings/lib/ SRC /lib.rs pub fn hello() {println! ("Hello, world!" ); } / / 03.1't/examples/hello/Cargo toml [package] name = "hello" version = "0.1.0 from the authors =" [" Dumindu Madunuwan "] [dependencies] greetings = { path = ".. /.. "} / lib / / 03.2't/examples/hello/SRC/main rs extern crate't; fn main() { greetings::hello(); }Copy the code
use
The main purpose of use is to simplify, without writing the full path for each call, for example:
mod phrases { pub mod greetings { pub fn hello() { println! ("Hello, world!" ); } } } fn main() { phrases::greetings::hello(); // using full path }Copy the code
The use of the use
use phrases::greetings;
fn main() {
greetings::hello();
}
// 02. create alias for module elements
use phrases::greetings::hello;
fn main() {
hello();
}
// 03. customize names with as keyword
use phrases::greetings::hello as greet;
fn main() {
greet();
}Copy the code
Another function of use is to pour elements into the current scope
fn hello() -> String { "Hello, world!" .to_string() } #[cfg(test)] mod tests { use super::hello; //import hello() into scope #[test] fn test_hello() { assert_eq! ("Hello, world!" , hello()); //if not using above use statement, we can run same via super::hello() } }Copy the code
Use Imports the standard library
use std::fs::File; fn main() { File::create("empty.txt").expect("Can not create the file!" ); } // -- 02. importing module and elements-- std::fs::{self, File} //use std::fs; use std::fs::File fn main() { fs::create_dir("some_dir").expect("Can not create the directry!" ); File::create("some_dir/empty.txt").expect("Can not create the file!" ); } // -- 03. importing multiple elements use std::fs::File; use std::io::{BufReader, BufRead}; //use std::io::BufReader; use std::io::BufRead; fn main() { let file = File::open("src/hello.txt").expect("file not found"); let buf_reader = BufReader::new(file); for line in buf_reader.lines() { println! ("{}", line.unwrap()); }}Copy the code
Pub use imports a member of a mod
mod phrases; fn main() { phrases::hello(); //not directly map} // ↳ phrases/mod.rs pub mod greetings; pub use self::greetings::hello; //re-export greetings::hello to phrases/ / ↳ phrases/greetings. Rs pub fn hello() {println! ("Hello, world!" ); }Copy the code
The standard library that Rust imports by default
// Reexported core operators
pub use marker::{Copy, Send, Sized, Sync};
pub use ops::{Drop, Fn, FnMut, FnOnce};
// Reexported functions
pub use mem::drop;
// Reexported types and traits
pub use boxed::Box;
pub use borrow::ToOwned;
pub use clone::Clone;
pub use cmp::{PartialEq, PartialOrd, Eq, Ord};
pub use convert::{AsRef, AsMut, Into, From};
pub use default::Default;
pub use iter::{Iterator, Extend, IntoIterator};
pub use iter::{DoubleEndedIterator, ExactSizeIterator};
pub use option::Option::{self, Some, None};
pub use result::Result::{self, Ok, Err};
pub use slice::SliceConcatExt;
pub use string::{String, ToString};
pub use vec::Vec;Copy the code