包、carte、模块

https://rustwiki.org/zh-CN/book/ch07-00-managing-growing-projects-with-packages-crates-and-modules.html

  • Packages): Cargo 的一个功能,它允许你构建、测试和分享 crate。

  • Crates :一个模块的树形结构,它形成了库或二进制项目。

  • 模块Modules)和 use: 允许你控制作用域和路径的私有性。

  • 路径path):一个命名例如结构体、函数或模块等项的方式

  1. crate是库

  2. crate root是库的源文件,编译的起点

  3. binary crate是库的二进制项

  4. packet 是包,一个包里边有一个或多个库,一个包有一个 Cargo.toml

  5. cargo new之后会生成一个包,rust 会默认创建一个叫做src/main.rs的crate root,这个是约定俗成。


我们用cargo new --lib restaurant来创建一个模块

然后修改其中的的src/lib.rs

mod front_of_house {
    mod hosting {
        fn add_to_waitlist() {}

        fn seat_at_table() {}
    }

    mod serving {
        fn take_order() {}

        fn serve_order() {}

        fn take_payment() {}
    }
}

它的模块树就是

crate
 └── front_of_house
     ├── hosting
     │   ├── add_to_waitlist
     │   └── seat_at_table
     └── serving
         ├── take_order
         ├── serve_order
         └── take_payment

接下来如果我们要引用包里边的成员,有两种方式:

  • 绝对路径absolute path)从 crate 根部开始,以 crate 名或者字面量 crate 开头。

  • 相对路径relative path)从当前模块开始,以 selfsuper当前模块的标识符开头。

另外,如果一个变量要暴露到他外边,需要用到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();
}

如果某一层要引用它上层的内容,就需要 super

fn serve_order() {}

mod back_of_house {
    fn fix_incorrect_order() {
        cook_order();
        super::serve_order();
    }

    fn cook_order() {}
}

我们还可以更精细化的指定 struct 和 enum 内部的成员是否是 pub

mod back_of_house {
    pub struct Breakfast { // 这里的 struct 没有 pub
        pub toast: String, // 可以指定内部的 toast 是 pub
        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_restaurant() {
    // 在夏天点一份黑麦面包作为早餐
    let mut meal = back_of_house::Breakfast::summer("Rye");
    // 更改我们想要的面包
    meal.toast = String::from("Wheat");
    println!("I'd like {} toast please", meal.toast);

    // 如果取消下一行的注释,将会导致编译失败;我们不被允许
    // 看到或更改随餐搭配的季节水果
    // meal.seasonal_fruit = String::from("blueberries");
}
mod back_of_house {
    pub enum Appetizer { // 直接把 enum 指定为 pub,内部的 Soup 和 Salad都是 pub
        Soup,
        Salad,
    }
}

pub fn eat_at_restaurant() {
    let order1 = back_of_house::Appetizer::Soup;
    let order2 = back_of_house::Appetizer::Salad;
}

use

use as

pub use

Cargo中假如 dependencies

嵌套 use

每次引用都需要假如一长串的后缀太麻烦了。所以感觉直接 use

注意我们习惯引入到模块,而不是引用到函数。所以下面例子是use crate::front_of_house::hosting;而不是use crate::front_of_house::hosting::add_to_waitlist;

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_restaurant() {
    hosting::add_to_waitlist();
}
fn main() {}

类似 python的 import as,rust 是 use as

use std::fmt::Result;
use std::io::Result as IoResult;

fn function1() -> Result {
    // --snip--
    Ok(())
}

fn function2() -> IoResult<()> {
    // --snip--
    Ok(())
}

重导出:pub use

让调用你编写的代码的代码能够像在自己的作用域内引用这些类型,可以结合 pubuse。这个技术被称为 “重导出re-exporting)”,因为这样做将项引入作用域并同时使其可供其他代码引入自己的作用域。

mod front_of_house {
    pub mod hosting {
        pub fn add_to_waitlist() {}
    }
}

pub use crate::front_of_house::hosting;

pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
}

Cargo.toml 中假如某个包然后才能 use

[dependencies]
rand = "0.8.3"
use rand::Rng;

fn main() {
    let secret_number = rand::thread_rng().gen_range(1..101);
}

嵌套 use,如果我们需要从一个包里边 use 很多东西。类似 python 的 from .. import 一大堆

// use std::cmp::Ordering;
// use std::io;
use std::{cmp::Ordering, io};

// use std::io;
// use std::io::Write;
use std::io::{self, Write};

// 引入所有内容
use std::collections::*;

例如我们想把上边的 add_to_waitlist放在自己的文件里边

src/front_of_house.rs
pub mod hosting {
    pub fn add_to_waitlist() {}
}
src/lib.rs
mod front_of_house;

pub use crate::front_of_house::hosting;

pub fn eat_at_restaurant() {
    hosting::add_to_waitlist();
}

可以进一步修改,(如果想扩充 host),src/lib.rs中的引用不会改变:

src/front_of_house/hosting.rs
pub fn add_to_waitlist() {}
src/front_of_house.rs
pub mod hosting;

最后更新于

这有帮助吗?