rust的代码组织可以分为函数,模块,crate,workspace。workspace管理不同的crate,crate管理不同的mod,mod管理不同的函数。
函数
函数是组织代码最小的单位例如:
fn main() {
greet(); //do one thing
ask_location(); //do another thing
}
fn greet() {
println!("Hello!");
}
fn ask_location() {
println!("Where are you from?");
}
在同一个文件中为函数添加单元测试
#[test]
fn test_greet() {
assert_eq!("Hello, world!", greet())
}
#[test]
属性表示这个函数是一个单元测试。
mod
mod 和代码放在同一个文件
fn main(){
greetings::hello();
}
mod greetings {
pub fn hello() {
println!("Hello world !");
}
}
嵌套mod
fn main(){
phrases::greetints::hello();
}
mod phrases {
pub mod greetings {
pub fn hello(){
println!("Hello, world!");
}
}
}
对于私有函数可以在同一mod或者子mod中调用
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();
}
}
}
在上面的程序中,self表示当前的mod,super表示父mod。
将mod分散到同一个路径下的不同文件中
// main.rs
mod greetings; // import greetings module
fn main() {
greetings::hello();
}
// greetings.rs
// 不需要显示声明mod,默认即是文件名作为mod名
pub fn hello() {
println!("Hello, world!");
}
如果mod文件中使用mod关键字包装:
// ↳ main.rs
mod phrases;
fn main() {
phrases::greetings::hello();
}
// ↳ phrases.rs
pub mod greetings {
pub fn hello() {
println!("Hello, world!");
}
}
mod 分散到不同路径的不同文件
mod.rs 是真个路径下的mod的入口文件,所有在同一路径下的文件都是它的子mod。
// ↳ main.rs
mod greetings;
fn main() {
greetings::hello();
}
// ↳ greetings/mod.rs
pub fn hello() {
println!("Hello, world!");
}
放到不同的文件下
// ↳ main.rs
mod phrases;
fn main() {
phrases::greetings::hello();
}
// ↳ phrases/mod.rs
pub mod greetings; // 在mod.rs 使用pub mod xxx 声明需要到出的mod
// ↳ phrases/greetings.rs
pub fn hello() {
println!("Hello, world!");
}
crate
lib.rs 和可执行文件在同一个crate中
当编写可执行文件的时候,可以将其他函数放到src/lib.rs 中,在src/main.rs 中引用使用
cargo new --bin greetings
touch greetings/src/lib.rs
// 01. greetings/src/lib.rs
pub fn hello() {
println!("Hello, world!");
}
// 02. greetings/src/main.rs
extern crate greetings;
fn main() {
greetings::hello();
}
lib.rs 文件中引用其他的文件
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;
在Cargo.toml 中声明依赖
基于文件路径的依赖:
[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();
}
基于git的依赖:
// -- 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" }
基于crates.io 版本
[dependencies]
test_crate_hello_world = "0.1.0"
workspace
当代码量越来越大的时候,一个项目可能包含了多个crate,rust通过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
│ └── hello
│ ├── Cargo.toml
│ └── src
│ └── main.rs
└── lib
├── Cargo.toml
└── 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 greetings/examples/hello/Cargo.toml
[package]
name = "hello"
version = "0.1.0"
authors = ["Dumindu Madunuwan"]
[dependencies]
greetings = { path = "../../lib" }
// 03.2 greetings/examples/hello/src/main.rs
extern crate greetings;
fn main() {
greetings::hello();
}
use
use 的主要作用就是简化,无需每次调用都写全路径,例如:
mod phrases {
pub mod greetings {
pub fn hello() {
println!("Hello, world!");
}
}
}
fn main() {
phrases::greetings::hello(); // using full path
}
使用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();
}
use 的另一个作用就是将元素倒入到当前作用域
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()
}
}
use 导入标准库
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());
}
}
pub use 将某个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!");
}
rust 默认导入的标准库
// 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;