Rust 第七节 - 包和模块

7 包和模块

7.1 二进制单元包(项目)和库单元包

7.1.1 什么是二进制单元包

二进制单元包也就是我们通过cargo new project生成的项目,最外层存在一个Cargo.toml的文件作为项目安装的文件目录,src/main.rs为该项目的根文件

7.1.2 什么是库单元包

而库单元包则是使用cargo new library --lib命令生成,src/lib.rs是该项目的根文件

7.1.3 单元包可以拆解成不同的模块

在Rust,库单元包可以由很多单元包组成,而单元包则可以由很多的模块组成

7.2 定义模块

那在Rust中我们应该怎么定义模块呢?我们需要使用关键字mod,例如:

rust 复制代码
mod my_module {}

我们可以在模块里面,定义函数,结构体,枚举,模块,例如:

rust 复制代码
mod my_module {
    fn test() {}
    mod other_module {}
    struct User {}
    enum Color {}
}

7.3 共有模块和私有模块

在模块中,Rust默认所有的属性都是私有属性,所以当我们需要在一个模块、文件中使用另外一个模块的内容,我们需要使用pub关键字声明它是一个公有属性,例如:

rust 复制代码
pub mod my_module {
    pub fn test() {}
    pub mod other_module {}
    pub struct User {}
    pub enum Color {}
}

其中结构体和枚举的共有声明有点差别,其中结构体不仅需要给自己添加pub关键字,自身的属性也需要添加才能对外暴露使用,而枚举之需要给自己添加pub即可,例如:

rust 复制代码
pub mod my_module {
    pub struct User {
        pub age: i8, // 公有
        name: String, // 私有
        email: String, // 私有
    }
    pub enum Color {
        Red, // 公有
        Green, // 公有
        Blue, // 公有
    }
}

7.4 引用模块

首先我们先声明一个模块,并且里面还包含了其他模块和方法,例如:

rust 复制代码
mod restaurant {
    pub mod free {
       pub fn add_rice() {}
    }
    mod money {
        fn add_vegetable(){}
        fn add_fruits() {}
    }
   
}

这里我们要讲到三个关键字,selfsupercrate,我们讲讲他们的作用。 其中self,表示它可以引用自身模块的项,例如:

rust 复制代码
mod restaurant {
    pub mod free {
       pub fn add_rice() {}
    }
    mod money {
        fn add_vegetable(){}
        fn add_fruits() {
            // 其中add_vegetable、add_fruits 是最近一个模块money的所属方法
            self::add_vegetable(); 
            self::add_fruits();
        }
    }
}

self::restaurant::free // 但是这样显得多次一举,我们可以直接 restaurant::free

对于super, 它代表的是以父模块开始的引用,可以引用父模块同层的变体,例如:

rust 复制代码
mod restaurant {
    pub mod free {
       pub fn add_rice() {}
    }
    mod money {
        fn add_vegetable(){}
        fn add_fruits() {
            super::free;  // 引用父模块的同层
            super::money; // 引用父模块的同层
        }
    }
    fn here(){
        super::user // 可以调用 模块 restaurant 同层的模块
    }
}

mod user {}

对于crate,表示的是从src/main.rs或者src/lib.rs模块开始的引用,表示为根目录,我们可以在根目录的任何层级中使用crate调用该文件中的任何共有的变体,例如:

rust 复制代码
mod restaurant {
    mod free {
        pub fn add_rice() {}
        mod soup {
            fn add_soup() {
                // 我们在这里如果想要使用money中的方法,只有使用crate才能拿到该方法
                crate::restaurant::money::add_vegetable()
            }
        }
    }
    mod money {
        pub fn add_vegetable() {}
        fn add_fruits() {}
    }
}

7.5 拆分文件

在日常开发中,我们肯定不会将所有的方法之类的放到一个文件夹中,所以我们可以将这些变体单独提取到一个文件中,我们新建一个文件和main.rs同层级,例如:

rust 复制代码
// 我们将上面的restaurant模块单独拆分到restaurant文件中
// restaurant.rs 
mod restaurant {
    pub mod free {
       pub fn add_rice() {}
    }
    mod money {
        fn add_vegetable(){}
        fn add_fruits() {}
    }
   
}

这个时候,我们需要在main.rs来引用这个文件中的模块,此时,我们需要使用use关键字,例如:

rust 复制代码
mod restaurant; // 等同于直接将文件引入进来
use restaurant::free; // 此时就可以可以用到该模块

当我们需要在当前的文件中,把引入的模块再此导出去供其他文件使用,我们可以在use前面加一个pub关键字,例如:

rust 复制代码
mod restaurant; 
pub use restaurant::free; // 此时外部可以使用free模块

7.4.3 全部引用

当我们想将一个模块中的所有变体都引入到当前的作用域中,我们可以使用*,例如:

rust 复制代码
use restaurant::*;

7.4.4 解构引用

我们也可以将引入的模块解构来使用,例如:

rust 复制代码
use restaurant::{free, free::add_rice};

7.4.5 重命名

我们在上面的引用,很有可能导致名字的重复,这个时候我们可以对引入的变体进行重命名,例如:

rust 复制代码
use restaurant::free as new_free;
相关推荐
晴殇i15 小时前
揭秘JavaScript中那些“不冒泡”的DOM事件
前端·javascript·面试
孟陬15 小时前
国外技术周刊 #1:Paul Graham 重新分享最受欢迎的文章《创作者的品味》、本周被划线最多 YouTube《如何在 19 分钟内学会 AI》、为何我不
java·前端·后端
BER_c15 小时前
前端权限校验最佳实践:一个健壮的柯里化工具函数
前端·javascript
兆子龙15 小时前
别再用 useState / data 管 Tabs 的 activeKey 了:和 URL 绑定才香
前端·架构
sudo_jin15 小时前
前端包管理器演进史:为什么 npm 之后,Yarn 和 pnpm 成了新宠?
前端·npm
叁两16 小时前
用opencode打造全自动公众号写作流水线,AI 代笔太香了!
前端·人工智能·agent
golang学习记16 小时前
GitLens 十大神技:彻底改变你在 VS Code 中的 Git 工作流
前端·后端·visual studio code
SuperEugene16 小时前
后台权限与菜单渲染:基于路由和后端返回的几种实现方式
前端·javascript·vue.js
兆子龙16 小时前
WebSocket 入门:是什么、有什么用、脚本能帮你做什么
前端·架构
是一碗螺丝粉16 小时前
LangChain 链(Chains)完全指南:从线性流程到智能路由
前端·langchain·aigc