手机设计企业网站,用静态网站更新,贵阳建设网站,网站如何设置长尾词文章目录 1. 前言2. 包和 Crate3. 定义模块以及模块之间的关系4. 作用域问题4.1. 作用域问题初现4.2. 解决问题一4.3. 解决问题二4.4. super 关键字4.5. 将路径引入作用域4.6. as 关键字4.7. pub use 重导出 5. 引入的问题5.1. 引入一个外部包5.2. 嵌套路径来消除大量的 use 行… 文章目录 1. 前言2. 包和 Crate3. 定义模块以及模块之间的关系4. 作用域问题4.1. 作用域问题初现4.2. 解决问题一4.3. 解决问题二4.4. super 关键字4.5. 将路径引入作用域4.6. as 关键字4.7. pub use 重导出 5. 引入的问题5.1. 引入一个外部包5.2. 嵌套路径来消除大量的 use 行5.3. 通过 glob 运算符将所有的公有定义引入作用域 6. 将模块拆分为多文件7. 小结 1. 前言
经过上一小节无聊又有趣的洗礼相信大家已经提起精神进入下一个内容的学习啦~~
这小节将会了解 Rust 中是以什么样的形式和工具来组织和管理自己的代码。我们都知道当代码量和源文件数量达到一定程度时候井然有序的组织将变得尤为重要不然我们的代码在外人眼里看来就是一坨*不仅其他人难以阅读作为开发者的你回头看去也是一头雾水悔恨自己写的这是个什么玩意儿。
在 Rust 中有着严格的作用域限制有这样的一个模块系统the model system来管理作用域其中包括
包PackagesCargo 的一个功能它允许你构建、测试和分享 crateCrates 一个模块的树形结构它形成了库或二进制项目模块Modules和 use允许你控制作用域和路径的私有性路径path一个命名例如结构体、函数或模块等项的方式。
2. 包和 Crate
crate 是 Rust 在编译时最小的代码单位。如果你用 rustc 而不是 cargo 来编译一个文件编译器还是会将那个文件认作一个 crate。crate 可以包含模块模块可以定义在其他文件然后和 crate 一起编译。
crate 有两种形式二进制项和库。二进制项可以被编译为可执行程序比如一个命令行程序或者一个 web server。它们必须有一个 main 函数来定义当程序被执行的时候所需要做的事情。目前我们所创建的 crate 都是二进制项。
库并没有 main 函数它们也不会编译为可执行程序库可以提供一些函数或结构体之类的就如之前我们所使用过的 rand 库就为我们提供了随机数函数。
包package是提供一系列功能的一个或者多个 crate。一个包会包含一个 Cargo.toml 文件阐述如何去构建这些 crate。Cargo 就是一个包含构建你代码的二进制项的包。Cargo 也包含这些二进制项所依赖的库。其他项目也能用 Cargo 库来实现与 Cargo 命令行程序一样的逻辑。
包中可以包含至多一个库 crate(library crate)。包中可以包含任意多个二进制 crate(binary crate)但是必须至少包含一个 crate无论是库的还是二进制的。
让我们来看看创建包的时候会发生什么。首先我们输入命令 cargo new my-project
$ cargo new my-projectCreated binary (application) my-project package
$ ls my-project
Cargo.toml
src
$ ls my-project/src
main.rsCargo 给我们创建了什么Cargo 会给我们的包创建一个 Cargo.toml 文件。查看 Cargo.toml 的内容会发现并没有提到 src/main.rs因为 Cargo 默认 src/main.rs 就是一个与包同名的二进制 crate 的 crate 根。
同样执行 cargo new --lib my-library 会有同样的目录结构生成不同的是这里的 src/main.rs 变成了 src/lib.rs并且 src/lib.rs 就是 crate 根。crate 根文件将由 Cargo 传递给 rustc 来实际构建库或者二进制项目。
这里只是包含一个 src/main.rs 的包意味着它只含有一个名为 my-project 的二进制 crate。如果一个包同时含有 src/main.rs 和 src/lib.rs则它有两个 crate一个二进制的和一个库的且名字都与包相同。通过将文件放在 src/bin 目录下一个包可以拥有多个二进制 crate每个 src/bin 下的文件都会被编译成一个独立的二进制 crate。
做个简单的实验首先执行 cargo new multiple_bin
$ cargo new multiple_bin
Creating binary (application) multiple_bin package
note: see more Cargo.toml keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
$ cd multiple_bin
$ tree
.
├── Cargo.lock
├── Cargo.toml
└── src└── main.rs进入 src创建 bin 目录并在其中创建多个 .rs 文件:
$ cd src
$ mkdir bin
$ cp ../main.rs bin01.rs
$ cp ../main.rs bin02.rs
$ cd ../../编译该项目
$ cargo buildCompiling multiple_bin v0.1.0 (/home/im01/Miracle/rust/multiple_bin)Finished dev profile [unoptimized debuginfo] target(s) in 0.11s
$ tree
.
├── Cargo.lock
├── Cargo.toml
├── src
│ ├── bin
│ │ ├── bin01.rs
│ │ └── bin02.rs
│ └── main.rs
└── target├── CACHEDIR.TAG└── debug├── bin01├── bin01.d├── bin02├── bin02.d├── build├── deps│ ├── bin01-54a8a90b566c47ce│ ├── bin01-54a8a90b566c47ce.d│ ├── bin02-057c31f4258a913d│ ├── bin02-057c31f4258a913d.d│ ├── multiple_bin-79155e437d2fa379│ └── multiple_bin-79155e437d2fa379.d├── examples├── incremental......├── multiple_bin└── multiple_bin.d15 directories, 48 files[注]这里为了简洁仅展示了部分主要内容。
从 target 目录可以看出这里不仅会为 main.rs 生成了与根同名的 multiple_bin 二进制的 crate还会为在 bin 目录下的两个文件生成对应文件名的二进制 crate。
3. 定义模块以及模块之间的关系
这里将会涉及到几个重要的关键字
use将路径引入作用域pub使对应项变为公有性质as为同名函数起别名。
在此之前先对几个概念做以解释
rust 项目是从 crate 根节点开始检索代码这很好理解对于一个二进制 crate 的根就是 src/main.rs而库则是 src/lib.rs就类似在 C/C 中总是以 main 函数开始声明模块在 crate 根文件中用 mod 关键字可以声明一个模块如 mod xiaomi_car; // 中国最大的保时捷法拉利元素融合高性能新能源汽车集团这便是声明了一个 xiaomi_car 模块而当 mod xiaomi_car 后是一个大括号时这样的方式成为内联如 mod xiaomi_car{fn sale() {} // 销售部销售小米汽车金牌销售员雷将军}声明子模块在不是 main.rs 中定义的模块被称为子模块公有和私有一个模块里的代码默认对其夫模块私有。为一个模块加上 pub 关键字即使用 pub mod 来声明模块则表示将该模块公有化
看完这些名词解释相信大家在大脑中还是一团浆糊那么接下来将通过一点小实验逐步让我们梳理清楚现在正在学习的到底是什么。
当下火出天际的汽车行业的雷小军的保时米为例来介绍保时米集团有这样的部门专门用来营销宣传以及销售汽车被称为销售部Sales Department还有专门用来生产制造的制造部Manufacturing Department。
好了现在让我们来创建一个小米汽车的库起名为 xiaomi_car。
$ cargo new --lib xiaomi_carCreating library xiaomi_car package
note: see more Cargo.toml keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html编辑 src/lib.rs 文件添加如下内容
mod sales_department {// 车辆售前服务mod pre_sales_service {// 车型咨询fn model_consultation() {}// 制定购车方案fn purchase_plan_options() {}}// 车辆售后服务mod after_sales_service {// 车辆保养服务fn vehicle_maintenance_services() {}// 维修服务fn repair_services() {}}
}这里我们用关键字 mod 定义了一个名为 sales_department 的模块接着花括号内为该模块的主体部分。在模块内仍然可以指定其它模块正如这里的 pre_sales_service 和 after_sales_service 模块是属于 sales_department 的子模块相应的 sales_department 是他们的父模块。而模块内还可以定义一些其它的各种类型如结构体、枚举、常量、函数等。
通过以模块的方式将相关的代码定义再一起这样会更有组织性的管理程序以 src/main.rs 或 src/lib.rs 作为 crate 根构成了一整个模块树module tree。
上面的代码就展示如下这样结构的设备树。
crate└── sales_department ├── pre_sales_service │ ├── model_consultation│ └── purchase_plan_options└── after_sales_service ├── vehicle_maintenance_services└── repair_services在 rust 里仍然是借用家庭关系来描述模块之间的关系在同一个模块中定义的子模块互为兄弟模块siblings module而包含着子模块的模块称为他们的父模块parent module。注意整个模块树都植根于名为 crate 的隐式模块下。这样一来我们就可以更加清晰的设计和组织我们的代码。
4. 作用域问题
4.1. 作用域问题初现
上面我们了解到模块之间的结构可以被抽象成为树状结构那么不同层之间的模块是否能够相互调用呢既然已经这么问了那么一定是不可以咯~总而言是先试试看吧。
// 保时米的销售部门
mod sales_department {// 车辆售前服务mod pre_sales_service {// 车型咨询fn model_consultation() {}// 制定购车方案fn purchase_plan_options() {}// 添加到生产订单fn add_to_production_order() {}}// 车辆售后服务mod after_sales_service {// 车辆保养服务fn vehicle_maintenance_services() {}// 维修服务fn repair_services() {}}
}// 保时米的生产制造部门
mod manufacturing_department {// 生产计划mod production_planning {// 制定生产计划fn specify_production_plan() {// 添加到生产订单add_to_production_order();}}// 总装车间mod final_assembly_workshop {}
}
让我们就这样编译看下能不能通过
im01Ubuntu:xiaomi_car$ cargo buildCompiling xiaomi_car v0.1.0 (/home/im01/Miracle/rust/xiaomi_car)
error[E0425]: cannot find function add_to_production_order in this scope-- src/lib.rs:23:13|
23 | add_to_production_order();| ^^^^^^^^^^^^^^^^^^^^^^^ not found in this scope|
note: function crate::sales_department::pre_sales_service::add_to_production_order exists but is inaccessible-- src/lib.rs:7:9|
7 | fn add_to_production_order() {}| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not accessibleFor more information about this error, try rustc --explain E0425.
error: could not compile xiaomi_car (lib) due to 1 previous error哦~哦吼吼~不出意外的出意外了从错误信息中可以看到没有在当前范围内找到 add_to_production_order 这个函数再看到下面的提示告诉我们说有一个同名的函数存在但是不可以访问。注意一下这里有两点问题
第一我们函数调用的方式不对因为调用了一个不存在的函数第二即便我们去调用这个存在的函数同样存在不可访问的问题。
4.2. 解决问题一
根据提示我们可以解决第一个问题修改上面代码
mod sales_department {mod pre_sales_service {//-------------snip----------------fn add_to_production_order() {}//-------------snip----------------}
}mod manufacturing_department {mod production_planning {fn specify_production_plan() {//add_to_production_order();// 绝对路径crate::sales_department::pre_sales_service::add_to_production_order();}}mod final_assembly_workshop {}
}pub fn sales_announcement() {// 相对路径sales_department::pre_sales_service::add_to_production_order();
}
[注]此处为了突出主要内容省略了部分无关代码。这里为了说明相对路径问题额外添加 sales_announcement 函数。
这里引入两个概念
绝对路径 从 crate 开始即从根开始按照树状结构索引出来的每一层之间用 :: 隔开相对路径 从当前位置出发即从同一层的模块位置出发索引同样每层之间用 :: 隔开。
好了这里我们编译一下看看会出现什么问题
im01Ubuntu:xiaomi_car$ cargo buildCompiling xiaomi_car v0.1.0 (/home/im01/Miracle/rust/xiaomi_car)
error[E0603]: module pre_sales_service is private-- src/lib.rs:25:38|
25 | crate::sales_department::pre_sales_service::add_to_production_order();| ^^^^^^^^^^^^^^^^^ ----------------------- function add_to_production_order is not publicly re-exported| || private module|
note: the module pre_sales_service is defined here-- src/lib.rs:2:5|
2 | mod pre_sales_service {| ^^^^^^^^^^^^^^^^^^^^^error[E0603]: module pre_sales_service is private-- src/lib.rs:37:23|
37 | sales_department::pre_sales_service::add_to_production_order();| ^^^^^^^^^^^^^^^^^ ----------------------- function add_to_production_order is not publicly re-exported| || private module|
note: the module pre_sales_service is defined here-- src/lib.rs:2:5|
2 | mod pre_sales_service {| ^^^^^^^^^^^^^^^^^^^^^For more information about this error, try rustc --explain E0603.
error: could not compile xiaomi_car (lib) due to 2 previous errors错误信息中告诉我们 pre_sales_service 是一个私有模块被 sales_department 模块私有因此外部无法访问这里所指的外部是 pre_sales_service 同层之外。
4.3. 解决问题二
此时的整个模块树看起来是这样的。
crate├── sales_department │ ├── pre_sales_service │ │ ├── model_consultation│ │ ├── purchase_plan_options│ │ └── add_to_production_order│ └── after_sales_service │ ├── vehicle_maintenance_services│ └── repair_services│└── manufacturing_department ├── production_planning │ └── specify_production_plan└── final_assembly_workshop 要想使得外部也可以访问这里就需要使用到关键字 pub。
mod sales_department {pub mod pre_sales_service {fn model_consultation() {}fn purchase_plan_options() {}fn add_to_production_order() {}}mod after_sales_service {fn vehicle_maintenance_services() {}fn repair_services() {}}
}//---------------snip---------------------------那么只在 pre_sales_service 前加上 pub 是否就可以了呢编译试试看
im01Ubuntu:xiaomi_car$ cargo buildCompiling xiaomi_car v0.1.0 (/home/im01/Miracle/rust/xiaomi_car)
error[E0603]: function add_to_production_order is private-- src/lib.rs:25:57|
25 | crate::sales_department::pre_sales_service::add_to_production_order();| ^^^^^^^^^^^^^^^^^^^^^^^ private function|
note: the function add_to_production_order is defined here-- src/lib.rs:7:9|
7 | fn add_to_production_order() {}| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^error[E0603]: function add_to_production_order is private-- src/lib.rs:37:42|
37 | sales_department::pre_sales_service::add_to_production_order();| ^^^^^^^^^^^^^^^^^^^^^^^ private function|
note: the function add_to_production_order is defined here-- src/lib.rs:7:9|
7 | fn add_to_production_order() {}| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^For more information about this error, try rustc --explain E0603.
error: could not compile xiaomi_car (lib) due to 2 previous errors正如之前所说外部无法访问指的外部是同层之外。因此 add_to_production_order 函数前也需要加上 pub。
mod sales_department {pub mod pre_sales_service {fn model_consultation() {}fn purchase_plan_options() {}pub fn add_to_production_order() {}}mod after_sales_service {fn vehicle_maintenance_services() {}fn repair_services() {}}
}//---------------snip---------------------------这样一来编译就没问题了。到这里相信大家已经粗略的感受到了在 rust 中作用域的概念。
4.4. super 关键字
这里换一种方式去调用 add_to_production_order。
mod sales_department {pub mod pre_sales_service {fn model_consultation() {}fn purchase_plan_options() {}pub fn add_to_production_order() {}}mod after_sales_service {fn vehicle_maintenance_services() {}fn repair_services() {}}
}mod manufacturing_department {mod production_planning {fn specify_production_plan() {//add_to_production_order();crate::sales_department::pre_sales_service::add_to_production_order();// 等同于上一行super::super::sales_department::pre_sales_service::add_to_production_order();}}mod final_assembly_workshop {}
}pub fn sales_announcement() {sales_department::pre_sales_service::add_to_production_order();
}此处便用到了 super 关键字其作用想必各位从形势中也窥窃出一二来没错 super 关键字的作用类似与 Linux 文件系统中的 .. 语法——到上一级目录而相应的这里则是到上一级模块层。
为什么 rust 会多此一举的设计这样的关键字原因很简单当全文都在使用绝对路径这样没错但会显得代码冗长。而全文又使用相对路径则会导致逻辑看起来混乱难以阅读一旦代码做过改动尤其是移动之后将会带来相应的错误而定位起来也较为不便那么有了 super 的引入之后我们很清楚的知道模块之间的关系当代码整体移动时也不必担心路径不对而需要修改调用路径。就是这样。
4.5. 将路径引入作用域
上面两个问题的解决方法虽然有效但是仍然让代码显得冗长这里将会介绍一个关键字 use 直接将需要的路径引入当前作用域可以极大的简化代码的长度。
mod sales_department {pub mod pre_sales_service {fn model_consultation() {}fn purchase_plan_options() {}pub fn add_to_production_order() {}}
}mod manufacturing_department {mod production_planning {// 使用 use 关键字use crate::sales_department::pre_sales_service;fn specify_production_plan() {//add_to_production_order();pre_sales_service::add_to_production_order();}}
}在当前作用域中增加 use 和路径类似于在文件系统中创建软连接符号连接symbolic link。需要注意的是use 只能对当前作用域范围内有效若上面代码改为如下这样则会无法使用到 use 引入进来的路径
mod sales_department {pub mod pre_sales_service {fn model_consultation() {}fn purchase_plan_options() {}pub fn add_to_production_order() {}}
}// 使用 use 关键字
use crate::sales_department::pre_sales_service;mod manufacturing_department {mod production_planning {fn specify_production_plan() {//add_to_production_order();pre_sales_service::add_to_production_order();}}
}事实上 use 也可以直接将其全部路径都引入像这样
mod sales_department {pub mod pre_sales_service {pub fn add_to_production_order() {}}
}mod manufacturing_department {mod production_planning {use crate::sales_department::pre_sales_service::add_to_production_order;fn specify_production_plan() {add_to_production_order();//pre_sales_service::add_to_production_order();}}
}直接引入 add_to_production_order 函数的完整路径这样的作法是允许的而常常的做法会像之前一样引入到其上一级这样编写的代码会很明确看出来该函数是别的模块而非当前模块。
4.6. as 关键字
这样引入完整路径会有什么问题吗假设有两个同名函数不同模块被同时引入呢
答案是rust 编译器将会告诉你这样的操作是不允许的。
那的确出现这样的情况怎么做这时候 rust 提供了我们另外一个关键字 as他可以为引入的变量或函数起别名就像这样
mod sales_department {pub mod pre_sales_service {pub fn test_func() {}}pub mod after_sales_service {pub fn test_func() {}}
}use crate::sales_department::pre_sales_service::test_func as pre_test_func;
use crate::sales_department::after_sales_service::test_func as after_test_func;
pub fn sales_announcement() {pre_test_func();after_test_func();
}使用 as 关键字让两个本来会使用冲突的函数同时可以引入当前作用域。
4.7. pub use 重导出
mod sales_department {pub mod pre_sales_service {pub fn add_to_production_order() {}}
}pub use crate::sales_department::pre_sales_service;pub fn sales_announcement() {pre_sales_service::add_to_production_order();
}这段代码与之前有所不同这里引入路径使用了 pub use 而非 use这样的作用是为了让外部代码也可以用这样的路径。
使用 use 关键字 在使用 use 引入路径时外部代码调用 add_to_production_order 需要指定其完整路径xiaomi_car::sales_department::pre_sales_service::add_to_production_order() 才能够调用该函数
使用 pub use 关键字 当使用 pub use 引入时外部代码则可以通过 xiaomi_car::pre_sales_service::add_to_production_order()来调用该函数仔细观察二者的区别这样可以省略中间的一大堆具体路径何乐而不为呢。
5. 引入的问题
5.1. 引入一个外部包
在之前我们编写了一个猜猜看游戏。那个项目使用了一个外部包rand来生成随机数。为了在项目中使用 rand在 Cargo.toml 中加入了如下行
rand 0.8.5在 Cargo.toml 中加入 rand 依赖告诉了 Cargo 要从 crates.io 下载 rand 和其依赖并使其可在项目代码中使用。
接着为了将 rand 定义引入项目包的作用域我们加入一行 use 起始的包名它以 rand 包名开头并列出了需要引入作用域的项。回忆一下之前的 “生成一个随机数” 部分我们曾将 Rng trait 引入作用域并调用了 rand::thread_rng 函数
use rand::Rng;fn main() {let secret_number rand::thread_rng().gen_range(1..100);
}crates.io 上有很多 Rust 社区成员发布的包将其引入你自己的项目都需要一道相同的步骤在 Cargo.toml 列出它们并通过 use 将其中定义的项引入项目包的作用域中。
注意 std 标准库对于你的包来说也是外部 crate。因为标准库随 Rust 语言一同分发无需修改 Cargo.toml 来引入 std不过需要通过 use 将标准库中定义的项引入项目包的作用域中来引用它们比如我们使用的 HashMap
use std::collections::HashMap;这是一个以标准库 crate 名 std 开头的绝对路径。
5.2. 嵌套路径来消除大量的 use 行
当需要引入很多定义于相同包或相同模块的项时为每一项单独列出一行会占用源码很大的空间。例如猜猜看代码中有两行 use 语句都从 std 引入项到作用域
// --snip--
use std::cmp::Ordering;
use std::io;
// --snip--相反我们可以使用嵌套路径将相同的项在一行中引入作用域。这么做需要指定路径的相同部分接着是两个冒号接着是大括号中的各自不同的路径部分
// --snip--
use std::{cmp::Ordering, io};
// --snip--在较大的程序中使用嵌套路径从相同包或模块中引入很多项可以显著减少所需的独立 use 语句的数量
我们可以在路径的任何层级使用嵌套路径这在组合两个共享子路径的 use 语句时非常有用。例如有两个 use 语句一个将 std::io 引入作用域另一个将 std::io::Write 引入作用域
use std::io;
use std::io::Write;两个路径的相同部分是 std::io这正是第一个路径。为了在一行 use 语句中引入这两个路径可以在嵌套路径中使用 self
use std::io::{self, Write};这一行代码便将 std::io 和 std::io::Write 同时引入作用域。
5.3. 通过 glob 运算符将所有的公有定义引入作用域
如果希望将一个路径下所有公有项引入作用域可以指定路径后跟 *——glob 运算符
use std::collections::*;这个 use 语句将 std::collections 中定义的所有公有项引入当前作用域。使用 glob 运算符时请多加小心Glob 会使得我们难以推导作用域中有什么名称和它们是在何处定义的。
glob 运算符经常用于测试模块 tests 中这时会将所有内容引入作用域。
6. 将模块拆分为多文件
到目前为止所有的例子都在一个文件中定义多个模块。当模块变得更大时你可能想要将它们的定义移动到单独的文件中从而使代码更容易阅读。
为了避免产生歧义这里贴出笔者希望拆分的原本代码
mod sales_department {pub mod pre_sales_service {fn model_consultation() {}fn purchase_plan_options() {}pub fn add_to_production_order() {}}pub mod after_sales_service {fn vehicle_maintenance_services() {}fn repair_services() {}}
}mod manufacturing_department {mod production_planning {fn specify_production_plan() {crate::sales_department::pre_sales_service::add_to_production_order();}}mod final_assembly_workshop {}
}pub fn sales_announcement() {
sales_department::pre_sales_service::add_to_production_order();
}首先尝试将 sales_department、manufacturing_department 模块拆分出去首先在 src 目录下创建 sales_department.rs 文件为其添加如下内容
pub mod pre_sales_service {fn model_consultation() {}fn purchase_plan_options() {}pub fn add_to_production_order() {}
}pub mod after_sales_service {fn vehicle_maintenance_services() {}fn repair_services() {}
}[注]这里是 src/sales_department.rs 文件
然后创建 manufacturing_department.rs 文件为其添加如下内容
mod production_planning {fn specify_production_plan() {crate::sales_department::pre_sales_service::add_to_production_order();}
}mod final_assembly_workshop {
}[注]这里是 src/manufacturing_department.rs 文件
然后再修改 src/lib.rs 文件内容
mod sales_department
mod manufacturing_departmentpub fn sales_announcement() {
sales_department::pre_sales_service::add_to_production_order();
}这样就完成了这两个模块的拆分。因为编译器找到了 crate 根中名叫 sales_department 的模块声明它就知道去搜寻 src/sales_department.rs 这个文件。
那如果还想继续拆分呢要怎么做其实道理相同下面笔者展示将 sales_department 模块继续拆分成多个文件。
首先在 src 目录下创建 sales_department 目录再进入 sales_department 目录分别创建文件 pre_sales_service.rs、after_sales_service.rs并为其添加如下内容
fn model_consultation() {}fn purchase_plan_options() {}pub fn add_to_production_order() {}[注]这里是 src/sales_department/pre_sales_service.rs 文件
fn vehicle_maintenance_services() {}fn repair_services() {}[注]这里是 src/sales_department/after_sales_service.rs 文件
这样一来就将该模块继续拆分为更多的文件这样拆分完后的文件目录结构如下。这个目录结构是不是很像我们的模块树。如果完全拆开那么这就是模块树。
im01Ubuntu:xiaomi_car$ tree
.
├── Cargo.lock
├── Cargo.toml
└── src├── lib.rs├── manufacturing_department├── manufacturing_department.rs├── sales_department│ ├── after_sales_service.rs│ └── pre_sales_service.rs└── sales_department.rs
各位应该看到 这里笔者提前创建了一个 manufacturing_department 目录各位同学可以自己尝试将 manufacturing_department 模块继续拆分。这个技巧让你可以在模块代码增长时将它们移动到新文件中。
注意我们只需在模块树中的某处使用一次 mod 声明就可以加载这个文件。一旦编译器知道了这个文件是项目的一部分并且通过 mod 语句的位置知道了代码在模块树中的位置项目中的其他文件应该使用其所声明的位置的路径来引用那个文件的代码这在“引用模块项目的路径”部分有讲到。换句话说mod 不是你可能会在其他编程语言中看到的 include 操作。
7. 小结
Rust 提供了将包分成多个 crate将 crate 分成模块以及通过指定绝对或相对路径从一个模块引用另一个模块中定义的项的方式。你可以通过使用 use 语句将路径引入作用域这样在多次使用时可以使用更短的路径。模块定义的代码默认是私有的不过可以选择增加 pub 关键字使其定义变为公有。
这一小节的文章很长笔者写的自认为也太过啰嗦能够坚持看完的你真的很厉害请收下笔者赠与的小红花万分感激您的阅读有任何疑问或问题还请不吝赐教~
下一篇《【Rust】集合的使用——Rust语言基础16》 觉得这篇文章对你有帮助的话就留下一个赞吧v* 请尊重作者转载还请注明出处感谢配合~ [作者]: Imagine Miracle [版权]: 本作品采用知识共享署名-非商业性-相同方式共享 4.0 国际许可协议进行许可。 [本文链接]: https://blog.csdn.net/qq_36393978/article/details/146339937