# 包和 Crate
一个包,包含一个或多个 crate,并且只有一个 Cargo.toml 文件,阐述如何构建这些 crate。
# 模块
// src/lib.rs | |
mod front_of_house { | |
mod hosting { | |
fn add_to_waitlist() {} | |
fn seat_at_table() {} | |
} | |
mod serving { | |
fn take_order() {} | |
fn server_order() {} | |
fn take_payment() {} | |
} | |
} |
相当于路径
crate
front_of_house
hosting
add_to_waitlist
seat_at_table
serving
take_order
server_order
take_payment
main.rs 和 lib.rs 都称为 crate 根
整个模块数都植根于隐式模块 crate 下
# 引用模块树的项
- 相对路径:以 self、super 来标识
- 绝对路径:以 crate 来标识
使用::分隔
mod front_of_house { | |
mod hosting { | |
fn add_to_waitlist() {} | |
} | |
} | |
pub fn eat_at_restaurant () { | |
// 绝对路径 | |
crate::front_of_house::hosting::add_to_waitlist(); | |
// 相对路径 | |
front_of_house::hosting::add_to_waitlist(); | |
} |
建议使用绝对路径,因为项目结构调整是经常的。
# 私有性边界
上面的代码编译会失败,因为知道路径,但有些是私有的,不给使用。
- Rust 中所有的条目默认是私有的:函数、方法、struct、enum、模块、常量
- 父级不能使用子级的东西,而子级可以使用父级的东西。
# pub - 使公有化
mod front_of_house { | |
pub mod hosting { | |
pub fn add_to_waitlist(){} | |
} | |
} | |
pub fn eat_at_restaurant() { | |
// 绝对路径 | |
crate::front_of_house::hosting::add_to_waitlist(); | |
// 相对路径 | |
front_of_house::hosting::add_to_waitlist(); | |
} |
内部的每一层都要加 pub 才能访问内部
同级是可以直接访问的
# super - 相对路径
super 可以改变模块访问边界,类似目录系统中的 ../ 上一层
fn server_order() {} | |
mod back_of_house { | |
fn fix_incorrect_order() { | |
cook_order(); | |
//super 改变路径位置 | |
// 注意:fn 不算是一层路径 | |
//mod 才是路径边界 | |
// 所以 super 是 back_of_house 的上一层 | |
super::server_order(); | |
} | |
fn cook_order() {} | |
} |
# pub struct
- pub 放在 struct 前:
- struct 是公共的
- struct 内的字段默认是私有的
- struct 字段前添加 pub 设置为公共的
mod back_of_house { | |
pub struct Breakfast { | |
pub toast: String, | |
seasonal_fruit: String, | |
} | |
impl Breakfast { | |
pub fn summer(toast: &str) -> Breakfast { | |
Breakfast { | |
toast: String::from(toast), | |
seasonal_fruit: String::from("peaches"), | |
} | |
} | |
} | |
} | |
pub fn eat_at_restuarant() { | |
let mut meal = back_of_house::Breakfast::summer("Rye"); | |
//toast 字段是公共的,外部可以访问 | |
meal.toast = String::from("Wheat"); | |
println!("I'd like {} toast please", meal.toast); | |
// 这里 seasonal_fruit 会报错,因为此字段是私有的,外部不可访问 | |
meal.seasonal_fruit = String::from("blueberries"); | |
} |
# pub enum
把 pub 放在 enum 前:
- enum 是公共的
- enum 的变体也都是公共的
mod back_of_house { | |
pub enum Appetizer { | |
// 以下变体,默认为公有的,此规则是例外;因为枚举在公共时才有意义 | |
Soup, | |
Salad, | |
} | |
} |
# use - 关键词
使用 use 关键字将路径导入到作用域内
- 可导入绝对路径或相对路径
mod front_of_house { | |
pub mod hosting { | |
pub fn add_to_waitlist() {}; | |
} | |
} | |
// 导入绝对路径,建议绝对路径 | |
use crate::front_of_house::hosting; | |
// 以下一行是导入相对路径 | |
// use front_of_house::hosting; | |
pub fn eat_at_restuarant() { | |
hosting::add_to_waitlist(); | |
hosting::add_to_waitlist(); | |
hosting::add_to_waitlist(); | |
} |
# use - 惯用用法
- 函数:将函数的父级模块引入作用域(指定到父级),目的:方便知道函数是外部还是当前文件定义的。
- struct、enum,其它:指定完整路径(指定到本身)
- 同名条目:指定到父级
use std::fmt; | |
use std::io; | |
// Result 同名,需要指定到父级 | |
fn f1() -> fmt::Result {/*impl*/} | |
fn f2() -> io::Result {/*impl*/} |
# as - 别名
as 关键字可以为 use 引入的路径指定本地的别名
use std::fmt::Result; | |
use std::io::Result as IoResult; | |
fn f1() -> Result {/*impl*/} | |
fn f2() -> IoResult {/*impl*/} |
# pub use - 重新导出名称
在 use 前面添加 pub,重导出模块
// 外部不能访问 | |
mod front_of_house { | |
pub mod hosting { | |
pub fn add_to_waitlist() {}; | |
} | |
} | |
// 重导出,这样外部能访问 hosting | |
pub use crate::front_of_house::hosting; | |
// 外部能访问 | |
pub fn eat_at_restuarant() { | |
hosting::add_to_waitlist(); | |
hosting::add_to_waitlist(); | |
hosting::add_to_waitlist(); | |
} |
# package - 使用外部包
- Cargo.toml 添加依赖的包(package):国内建议配置镜像
- https://crates.io
- use 将依赖包内特定的条目引入到作用域
# 嵌套路径 - 优化 use 语句
如果使用同一个包或模块下的多个条目,则导致多条 use 语句。可以提取公共部分,把不同的部分放到嵌套路径上。
路径相同部分::{路径差异的部分}
// use std::cmp::Ordering; | |
// use std::io; | |
// 使用嵌套路径优化 | |
use std::{cmp::Ordering, io}; | |
fn main{} |
- 如果两个 use 路径之一是另外一个的子路径时:
// use std::io; | |
// use std::io::Write; | |
// 使用嵌套路径,以及 self 优化路径 | |
use std::io::{self, Write}; |
# 通配符 *
- 使用 * 可以把路径中所有的公共条目都引入到作用域。
- 应用场景:
- 测试。(将所有被测试代码引入到 tests 模块)
- 用于预导入(prelude)模块
# 将模块拆分到其它文件
模块定义时,如果模块名后面是
;结尾,而不是代码块时:- rust 会从与模块同名的文件中加载内容
// 文件:src/lib.rs//rust 会找此文件目录下的 front_of_house.rs 文件mod front_of_house;
// 文件:src/front_of_house.rspub mod hosting {
pub fn add_to_waitlist() {}
}多层模块嵌套时:
// 文件:src/lib.rs | |
//rust 会找此文件目录下的 front_of_house.rs 文件 | |
mod front_of_house; |
// 文件:src/front_of_house.rs | |
//rust 会找此文件目录下的 front_of_house/hosting.rs 文件 | |
pub mod hosting; |
// src/front_of_house/hosting.rs | |
pub fn add_to_waitlist() {} |