Updated src/packages_crates_and_modules/the_use_keyword.md'.

This commit is contained in:
Hector PENG
2026-03-15 18:36:11 +08:00
parent ed872807fb
commit fb2dcc8328
7 changed files with 105 additions and 95 deletions

View File

@@ -1,17 +1,15 @@
mod back_of_house { mod front_of_house {
#[derive(Debug)] pub mod hosting {
pub enum Appetizer { pub fn add_to_waitlist() {}
Soup,
Salad,
} }
} }
pub fn eat_at_restaurant() { use crate::front_of_house::hosting;
let order1 = back_of_house::Appetizer::Soup;
let order2 = back_of_house::Appetizer::Salad;
println! (" pub mod customer {
{order1:?} use super::hosting;
{order2:?}
"); pub fn eat_at_restaurant() {
hosting::add_to_waitlist();
}
} }

View File

@@ -1,5 +1,5 @@
use restaurant::*; use restaurant::customer;
fn main() { fn main() {
eat_at_restaurant(); customer::eat_at_restaurant();
} }

View File

@@ -0,0 +1,6 @@
[package]
name = "use_demo"
version = "0.1.0"
edition = "2024"
[dependencies]

View File

@@ -0,0 +1,8 @@
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert(1, 2);
println! ("{map:?}");
}

View File

@@ -143,9 +143,7 @@ error: doctest failed, to rerun pass `--doc`
程序项目里的文档注释用于对描述代码箱及模组尤其有用。使用他们来解释容器the container的整体目标有助于咱们的用户们理解代码箱的组织结构。 程序项目里的文档注释用于对描述代码箱及模组尤其有用。使用他们来解释容器the container的整体目标有助于咱们的用户们理解代码箱的组织结构。
## 使用 `pub use` 导出便利的公开 API ## 导出便利的公开 API
**Exporting a Convinient Public API with `pub use`**
在咱们发布代码箱时,公开 API 的结构是主要的考量。相比与咱们,使用咱们代码箱的人们对代码箱结构的没有那么熟悉,并在咱们的代码箱有着大型模组层次结构时,难于找到他们打算使用的部分。 在咱们发布代码箱时,公开 API 的结构是主要的考量。相比与咱们,使用咱们代码箱的人们对代码箱结构的没有那么熟悉,并在咱们的代码箱有着大型模组层次结构时,难于找到他们打算使用的部分。

View File

@@ -315,7 +315,7 @@ pub fn eat_at_restaurant() {
除非枚举的变种是公开的,否则枚举的用处就不大;在每种情况下都必须以 `pub` 注解所有枚举变种将很烦人了,因此枚举变种的默认设置是要成为公开。结构体在其字段不公开的情况下通常就很有用,因此结构体字段遵循默认情况下所有内容都是私有,除非以 `pub` 注释的一般规则。 除非枚举的变种是公开的,否则枚举的用处就不大;在每种情况下都必须以 `pub` 注解所有枚举变种将很烦人了,因此枚举变种的默认设置是要成为公开。结构体在其字段不公开的情况下通常就很有用,因此结构体字段遵循默认情况下所有内容都是私有,除非以 `pub` 注释的一般规则。
还有一种涉及 `pub` 的情形我们尚未介绍,那就我们的最后一项模组系统特性:`use` 关键字。我们将首先介绍 `use` 本身,然后我们将展示如何结合 `pub``use` 还有一种涉及 `pub` 的情形我们尚未介绍,那就我们的最后一项模组系统特性:`use` 关键字。我们将首先介绍 `use` 本身,然后我们将展示如何结合 `pub``use`
End End

View File

@@ -1,12 +1,9 @@
# 使用 `use` 关键字将路径纳入作用域 # `use` 关键字带入路径到作用域
**Bringing Paths into Scope with the `use` Keyword** 必须写出调用函数的路径可能会感到不便且重复。在 [清单 7-7](paths.md#listing_7-7) 中,无论我们选择 `add_too_waitlist` 函数的绝对路径还是相对路径,每次我们想要调用 `add_too_waitlist` 时,我们都必须还要指定 `front_of_house``hosting`。幸运的是,有一种简化这一过程的方式:我们可以 `use` 关键字创建路径的快捷方式一次,然后在作用域中的其他地方使用较短的名字。
必须写出调用函数的路径,可能会让人感到不便和重复。在 [清单 7-7](paths.md#list_7-7) 中,无论我们选择 `add_too_waitlist` 函数的绝对路径还是相对路径,每次要调用 `add_too_waitlist` 时,都必须指定 `front_of_house``hosting`。幸运的是,有种方法可以简化这一过程:我们可以使用 `use` 关键字,为路径创建一个快捷方式,然后在作用域的其他地方,使用这个较短的名字 在下面清单 7-11 中,我们将 `crate::front_of_house::hosting` 模组带入 `eat_at_restaurant` 函数的作用域,这样我们只需指定 `hosting::add_too_waitlist` 即可在 `eat_at_restaurant` 中调用 `add_too_waitlist` 函数
在清单 7-11 中,我们将 `crate::front_of_house::hosting` 模组,引入了 `eat_at_restaurant` 函数的作用域,因此只需指明 `hosting::add_too_waitlist`,就能调用 `eat_at_restaurant` 中的 `add_too_waitlist` 函数。
<a name="list_7-11"></a>
文件名:`src/lib.rs` 文件名:`src/lib.rs`
```rust ```rust
@@ -23,11 +20,12 @@ pub fn eat_at_restaurant() {
} }
``` ```
*清单 7-11使用 `use` 关键字,将模组纳入作用域* <a name="listing_7-11"></a>
**清单 7-11**:以 `use` 关键字带入模组到作用域
某个作用域中加 `use` 关键字及某个路径,类似于在文件系统中创建一个符号链接。通过在代码箱根添加 `use crate::front_of_house::hosting``hosting` 现在便是该作用域中的一个有效名字,就像在代码箱根中已经定义了 `hosting` 模组一样。使用 `use` 关键字入作用域的路径也会像其他路径一样检查隐私。 在作用域中`use` 路径,类似于在文件系统中创建符号链接。通过在代码箱根添加 `use crate::front_of_house::hosting``hosting` 现在便是该作用域中的有效名字,就像 `hosting` 模组已在代码箱根处定义一样。与任何其他路径一样,以 `use` 关键字入作用域的路径也会检查隐私。
请注意,`use` 关键字只会为该 `use` 语句所在的特定作用域创建快捷方式。清单 7-12 `eat_at_restaurant` 函数,移到了一个名为 `customer` 的新子模组中,该子模组的作用域`use` 语句的作用域不同,因此这个函数体就无法编译。 请注意,`use` 只会针对 `use` 发生之处的作用域创建快捷方式。下面清单 7-12 迁移 `eat_at_restaurant` 函数一个名为 `customer` 的新子模组中,该子模组是个`use` 语句不同的作用域,因此函数体将不编译。
文件名:`src/lib.rs` 文件名:`src/lib.rs`
@@ -48,40 +46,46 @@ mod customer {
} }
``` ```
*清单 7-12`use` 语句只适用于他所在的作用域* <a name="listing_7-12"></a>
**清单 7-12**`use` 语句仅应用于其所在的作用域
编译器错误显示,快捷方式不再适用于这个 `customer` 模组: 编译器错误表明该快捷方式 `customer` 模组内不再适用
```console ```console
$ cargo build $ cargo build
Compiling restaurant v0.1.0 (/home/peng/rust-lang/restaurant) Compiling restaurant v0.1.0 (/home/hector/rust-lang-zh_CN/projects/restaurant)
error[E0433]: failed to resolve: use of undeclared crate or module `hosting` error[E0433]: failed to resolve: use of unresolved module or unlinked crate `hosting`
--> src/lib.rs:33:9 --> src/lib.rs:11:9
|
11 | hosting::add_to_waitlist();
| ^^^^^^^ use of unresolved module or unlinked crate `hosting`
|
= help: if you wanted to use a crate named `hosting`, use `cargo add hosting` to add it to your `Cargo.toml`
help: consider importing this module through its public re-export
|
10 + use crate::hosting;
| |
33 | hosting::add_to_waitlist();
| ^^^^^^^ use of undeclared crate or module `hosting`
warning: unused import: `crate::front_of_house::hosting` warning: unused import: `crate::front_of_house::hosting`
--> src/lib.rs:28:5 --> src/lib.rs:7:5
| |
28 | use crate::front_of_house::hosting; 7 | use crate::front_of_house::hosting;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
= note: `#[warn(unused_imports)]` on by default = note: `#[warn(unused_imports)]` (part of `#[warn(unused)]`) on by default
For more information about this error, try `rustc --explain E0433`. For more information about this error, try `rustc --explain E0433`.
warning: `restaurant` (lib) generated 1 warning warning: `restaurant` (lib) generated 1 warning
error: could not compile `restaurant` due to previous error; 1 warning emitted error: could not compile `restaurant` (lib) due to 1 previous error; 1 warning emitted
``` ```
请注意这里还有个警告,即在其作用域中那个 `use` 不再被用到!要解决这个问题,同时要把这个 `use` 语句,移`customer` 模组中,或者在 `customer` 子模组中,使用 `super::hosting` 引用父模组中的那个快捷方式。 请注意,还有一条告警,表明其中的 `use` 在其作用域中不在被用到!要修复这个问题,也要迁移这个 `use` 语句到 `customer` 模组中,或者在 `customer` 子模组内以 `super::hosting` 引用父模组中的快捷方式。
## 创建惯用 `use` 路径 ## 创建惯用 `use` 路径
**Creating Idiomatic `use` Paths** 在 [清单 7-11](#listing_7-11) 中,咱们可能想知道为什么我们指定了 `use crate::front_of_house::hosting`,然后在 `eat_at_restaurant` 中调用 `hosting::add_to_waitlist`,而不是指定 `add_too_waitlist` 函数的完整 `use` 路径,如下面清单 7-13 中那样。
在 [清单 7-11](#list_7-11) 中,咱们可能想知道,为什么我们指定了使用 `crate::front_of_house::hosting`,然后在 `eat_at_restaurant` 中调用 `hosting::add_to_waitlist`,而不是像清单 7-13 中那样,为了达到同样的效果,指定出直达 `add_too_waitlist` 函数的 `use` 路径。
文件名:`src/lib.rs` 文件名:`src/lib.rs`
@@ -99,11 +103,12 @@ pub fn eat_at_restaurant() {
} }
``` ```
*清单 7-13使用 `use` 将 `add_to_waitlist` 纳入作用域,这种非惯常用法* <a name="listing_7-13"></a>
**清单 7-13**:以 `use` 带入 `add_to_waitlist` 到作用域,这属于非惯用的
尽管清单 7-11 和清单 7-13 都完成了同任务,但清单 7-11 是将函数纳入作用域的惯用方法。使用 `use` 函数的父模组纳入作用域意味着我们必须在调用函数时,指明其父模组。在调用函数时指定父模组可以清楚地表明该函数不本地定义的,同时仍然最大限度减少完整路径的重复。清单 7-13 中的代码并不明晰,因为`add_too_waitlist` 的定义位置不明晰 尽管清单 7-11 和清单 7-13 都完成了同任务,但清单 7-11 是`use` 带入函数到作用域的惯用方式。以 `use` 带入函数的父模作用域意味着我们在调用函数时必须指定父模组。在调用函数时指定父模组可以清楚地表明该函数不属于本地定义的,同时仍然最大限度减少完整路径的重复。清单 7-13 中的代码`add_too_waitlist` 于何处定义方面不清楚
另一方面,在以 `use` 关键字引入结构体、枚举及其他一些项目时,指定完整路径就是种习惯做法。清单 7-14 展示了标准库的 `HashMap` 结构体,纳入某个二进制代码箱作用域的惯用方 另一方面,在以 `use` 关键字引入结构体、枚举及其他项目时,指定完整路径是惯用的。下面清单 7-14 展示了带入标准库的 `HashMap` 结构体二进制代码箱作用域的惯用方
文件名:`src/main.rs` 文件名:`src/main.rs`
@@ -116,11 +121,12 @@ fn main() {
} }
``` ```
*清单 7-14以惯用方式将 `HashMap` 纳入作用域* <a name="listing_7-14"></a>
**清单 7-14**:以惯用方式带入 `HashMap` 到作用域
这个习惯用法背后,并没有很强的理由:他只是种约定俗成的习惯,人们已经习惯了这种方式,来阅读和编写 Rust 代码。 这个习惯用法背后没有什么强有力的理由:他只是已经出现的约定,人们已经习惯了这种方式阅读和编写 Rust 代码。
如果我们要使用 `use` 语句,将两个同名项目纳入作用域,那么这个习惯用法就是个例外,因为 Rust 不允许这样做。清单 7-15 展示了如何将两个名字相同但父模组不同`Result` 类型纳入作用域,以及如何引用他们。 这种习惯用法的例外,是当我们以 `use` 语句带入两个同名项目作用域,因为 Rust 不允许这样做。下面清单 7-15 展示了如何带入两种有着同一名字但不同父模组的 `Result` 类型作用域,以及如何引用他们。
文件名:`src/lib.rs` 文件名:`src/lib.rs`
@@ -137,16 +143,15 @@ fn function2() -> io::Result {
} }
``` ```
*清单 7-15将两个同名类型纳入同一作用域就需要用到他们的父模组* <a name="listing_7-15"></a>
**清单 7-15**:带入两个有着相同名字的类型到同一作用域必须用到他们的父模组
正如咱们所见到的,使用父模组就可以区分两种 `Result` 类型。而如果我们指定了 `use std::fmt::Result``use std::io::Result`,我们就会在同一作用域中,有了两个 `Result` 类型,但 Rust 不会知道,我们使用 `Result` 时指的是哪个。 正如咱们所见,使用父模组区分两种 `Result` 类型。相反,若我们指定了 `use std::fmt::Result``use std::io::Result`,我们就会在同一作用域中两个 `Result` 类型,并且当我们使用 `Result`Rust 将不清楚我们指的是哪个。
## 使用 `as` 关键字提供新名字 ## `as` 关键字提供新名字
**Providing New Names with the `as` Keyword** 对于以 `use` 带入两种同名类型到同一作用域的问题,还有另一种解决方案:在路径后,我们可以为类型指定 `as` 及一个新的本地名字,或 *别名alias*。下面清单 7-16 展示了编写清单 7-15 中代码的另一种方式,通过使用 `as` 重命名两种 `Result` 类型中之一。
还有另一种方法,可以解决将两个同名类型纳入同一作用域的问题:在路径之后,我们可以指定 `as` 和一个新的本地名字,或 *别名alias*。清单 7-16 展示了另一种编写清单 7-15 代码的方法,即使用 `as` 重命名两个 `Result` 类型中的一个。
文件名:`src/lib.rs` 文件名:`src/lib.rs`
@@ -163,18 +168,17 @@ fn function2() -> IoResult {
} }
``` ```
*清单 7-16将某个类型纳入作用域时使用 `as` 关键字对其重命名* <a name="listing_7-16"></a>
**清单 7-16**:当带入类型到作用域时以 `as` 关键字重命名类型
在第二个 `use` 语句中,我们为 `std::io::Result` 类型选择了新名字 `IoResult`,这不会与我们同时引入该作用域的 `std::fmt` 中的 `Result` 冲突。清单 7-15 和清单 7-16 都被认为是惯用的,因此选择由咱们自己决定 在第二个 `use` 语句中,针对 `std::io::Result` 类型我们选择了新名字 `IoResult`,这不会与我们同样带入作用域的 `std::fmt` 中的 `Result` 冲突。清单 7-15 和清单 7-16 均被视为惯用的,因此选择取决于咱们
## 使用 `pub use` 重新导出名字 ## `pub use` 导出名字
**Re-exporting Names with `pub use`** 当我们以 `use` 关键字带入名字到作用域后,该名字对于我们将其导入的作用域是私有的。为了该作用域外部的代码能够引用这个名字,就好像他已在该作用域中定义那样,我们可以结合 `pub``use`。这项技巧称为 *再导出re-exporting*,因为我们在带入项目到作用域的同时,还构造该项目为可供其他人带入他们的作用域。
当我们使用 `use` 关键字将名字纳入作用域时,新作用域中可用的这个名字是私有的。为了使调用咱们代码的代码,就好像这个名字是在咱们代码作用域中定义的那样,引用这个名字,我们可以将 `pub``use` 结合使用。这种技术被称为 *再导出re-exporting*,因为我们在将某个项目纳入作用域的同时,还让其他人可以将该项目纳入他们的作用域了 下面清单 7-17 展示 [清单 7-11](#listing_7-11) 中的代码,其中根模组中的 `use` 已改为 `pub use`
清单 7-17 展示清单 7-11 中的代码,其中根模组中的 `use` 已更改为 `pub use`
文件名:`src/lib.rs` 文件名:`src/lib.rs`
@@ -192,18 +196,17 @@ pub fn eat_at_restaurant() {
} }
``` ```
<a name="listing-7-17"></a> *清单 7-17使用 `pub use` 让任何代码都可以从新作用域中使用某个名字* <a name="listing_7-17"></a>
**清单 7-17**:以 `pub use` 在新的作用域中构造项目为可供任何代码使用
在这一修改前,外部代码必须使用 `restaurant::front_of_house::hosting::add_too_waitlist()` 路径,来调用 `add_to_waitlist` 函数,这还需要 `front_of_house` 模组标记为 `pub`。现在,这个 `pub use`经从该根模组中,重新导出了 `hosting` 模组,外部代码就可以使用 `restaurant::hosting::add_to_waitlist()` 路径了 在这一修改前,外部代码必须通过使用路径 `restaurant::front_of_house::hosting::add_too_waitlist()` 路径调用 `add_to_waitlist` 函数,这还需要 `front_of_house` 模组标记为 `pub`。现在,这个 `pub use`重导出了根模组中的 `hosting` 模组,外部代码便可使用路径 `restaurant::hosting::add_to_waitlist()`
当咱们代码的内部结构与调用咱们代码的程序员对有关领域的理解有差别时,重导出非常有用。例如,在这个餐馆的比方中,经营餐的人考虑的是“前厅”“后厨”。但光顾餐厅的顾客可能不会从这些角度来考虑餐厅的各个部分。通过 `pub use`,我们可以一种结构编写代码,而暴露出不同的结构。这样做可以使我们的程序库井井有条,便于编写这个库的程序员,也便于调用这个库的程序员。我们将在第 14 章的 [使用 `pub use` 导出好用的公开 API”](../crates-io/publishing.md##使用-pub-use-导出便利的公开-api) 小节,介绍 `pub use` 的另一个示例,以及他代码箱文档的影响 当咱们代码的内部结构不同于与调用咱们代码的程序员,对这一领域的理解方式时,重导出非常有用。例如,在这个餐厅比喻中,经营餐的人考虑的是 “前厅”“后厨”。但光顾餐厅的顾客可能不会从这些方面考虑餐厅的各个部分。 `pub use`,我们可以一种结构编写咱们的代码,而暴露另一种结构。这样做使我们的库对在这个库上工作及调用库的程序员,都能保持组织良好。我们将在第 14 章的 [导出便利的公开 API”](../crates-io/publishing.md##导出便利的公开-api) 小节中,探讨 `pub use` 的另一个示例,以及他如何影响咱们的代码箱文档。
## 使用外部包 ## 使用外部包
**Using External Packages** 在第 2 章中,我们编写了个猜数游戏项目,使用了一个名为 `rand` 的外部包来获取随机数。为了在咱们的项目中使用 `rand`,我们添加了下面这行到 `Cargo.toml`
在第 2 章中,我们编写了个竞猜游戏项目,该项目使用了名为 `rand` 的外部包,来获取随机数。为了在项目中使用 `rand`,我们在 `Cargo.toml` 中添加了这一行:
文件名:`Cargo.toml` 文件名:`Cargo.toml`
@@ -211,9 +214,9 @@ pub fn eat_at_restaurant() {
rand = `0.8.5` rand = `0.8.5`
``` ```
`Cargo.toml` 中将 `rand` 添加为依赖项Cargo 就会从 [crates.io](https://crates.io/) 下载 `rand`任何依赖项,并将 `rand` 提供到咱们的项目。 `Cargo.toml` 添加 `rand` 为依赖项,告诉 Cargo 从 [crates.io](https://crates.io/) 下载 `rand`任何依赖项,而使 `rand` 咱们的项目可用
然后,为了 `rand` 定义带入咱们包的作用域,我们添加了以代码箱名字 `rand` 开头的 `use` 行,并列出了咱们打算带入作用域的那些项目。清回想一下,在第 2 章 [“生成随机数”](../Ch02_Programming_a_Guessing_Game.md#生成随机数) 小节中,我们 `Rng` 特质引入了作用域并调用了 `rand::thread_rng` 函数: 然后,为了带入 `rand` 定义咱们包的作用域,我们添加了以这个代码箱名字 `rand` 开头的 `use` 行,并列出了咱们打算带入作用域的项目。回顾在第 2 章中的 [“生成随机数”](../Ch02_Programming_a_Guessing_Game.md#生成随机数) 小节中,我们带入了 `Rng` 这个特质到作用域并调用了 `rand::thread_rng` 函数:
```rust ```rust
use rand::Rng; use rand::Rng;
@@ -223,23 +226,20 @@ fn main() {
} }
``` ```
Rust 社区成员在 [crates.io](https://crates.io/) 上,已经提供了许多包,其中任何包拉入咱们的包,都需要这些同样步骤:在咱们包的 `Cargo.toml` 文件中列出他们,并使用 `use` 他们代码箱中的项目,引入到作用域。 Rust 社区成员在 [crates.io](https://crates.io/) 提供了许多包,而拉取其中任何包咱们的包中都涉及这些同样步骤:在咱们包的 `Cargo.toml` 文件中列出他们,并使用 `use` 带入他们代码箱中的项目到作用域。
请注意,标准 `std` 同样属于相对于咱们包外部的一个代码箱。因为标准库是随 Rust 语言一起提供的,所以我们不需要修改 `Cargo.toml` 来包含 `std`。但我们确实需要 `use` 引用他,以便将其中的项目引入咱们包的作用域。例如,对于 `HashMap` 我们可以使用这行: 请注意,标准 `std` 同样属于咱们包外部的代码箱。因为标准库是随 Rust 语言一起提供的,所以我们不需要修改 `Cargo.toml` 来包含 `std`。但我们确实需要 `use` 引用他,来带入其中的项目咱们包的作用域。例如,对于 `HashMap` 我们将使用下面这行:
```rust ```rust
use std::collections::HashMap; use std::collections::HashMap;
``` ```
这是个以 `std`标准库代码箱名字开头的绝对路径。 这是个以 `std`,即标准库代码箱名字开头的绝对路径。
## 使用嵌套路径清理大型 `use` 清单 ## 使用嵌套路径清理 `use` 列表
**Using Nested Paths to Clean Up Large `use` Lists** 当我们正使用定义在同一代码箱或同一模组中的多个项目时,那么在每个项目自己的行上列出他们就会占用咱们文件中的大量垂直空间。例如,我们在猜数游戏处的 [清单 2-4](Ch02_Programming_a_Guessing_Game.md#listing_2-4) 中有的这两条 `use` 语句,会带入 `std` 中的项目到作用域:
如果我们使用的是定义在同一代码箱,或同一模组中的多个项目,而将每个项目单独列一行,就会占用文件中的大量垂直空间。例如,我们在 [清单 2-4](Ch02_Programming_a_Guessing_Game.md#list_2-4) 的猜谜游戏中,使用的这两条 `use` 语句,将 `std` 中的项目引入了作用域:
文件名:`src/main.rs` 文件名:`src/main.rs`
@@ -250,7 +250,7 @@ use std::io;
// --跳过-- // --跳过--
``` ```
实际上,我们可以使用嵌套路径,在一行中将同样这些项目纳入作用域。具体做法是指定路径的共同部分,后面加两个冒号,然后在这些项目的路径不同部分列表周围,加上花括号,如清单 7-18 所示。 相反,我们可以使用嵌套路径一行中带入同样的项目到作用域。通过指定路径的共同部分,后两个冒号,然后用花括号括起一个路径不同部分列表,如清单 7-18 所示。
文件名:`src/main.rs` 文件名:`src/main.rs`
@@ -260,11 +260,12 @@ use std::{cmp::Ordering, io};
// --跳过-- // --跳过--
``` ```
*清单 7-18指定嵌套路径将具有同样前缀的多个项目纳入作用域* <a name="listing_7-18"></a>
**清单 7-18**:指定嵌套路径以带入有着同一前缀的多个项目到作用域
大型程序中,使用嵌套路径同一代码箱或同一模组中的许多项目引入作用域,可大大减少所需的单独 `use` 语句数量! 较大的程序中,使用嵌套路径带入同一代码箱或同一模组中的许多项目作用域,可大大减少所需的单独 `use` 语句数量!
在路径的任何层级,我们都可以使用嵌套路径,在对共用子路径的两个 `use` 语句加以组合时,这尤为有用。例如,清单 7-19 给出了两 `use` 语句:一个 `std::io` 引入作用域,另一个 `std::io::Write` 引入作用域。 我们可在路径的任何级别使用嵌套路径,这在组合两条共用子路径的 `use` 语句时非常有用。例如,下面清单 7-19 显示了两 `use` 语句:一个带入 `std::io` 作用域,另一个带入 `std::io::Write` 作用域。
文件名:`src/lib.rs` 文件名:`src/lib.rs`
@@ -274,9 +275,10 @@ use std::io;
use std::io::Write; use std::io::Write;
``` ```
*清单 7-19两个 `use` 语句,其中一个是另一个的子路径* <a name="listing_7-19"></a>
**清单 7-19**:两条 `use` 语句,其中一条是另一条的子路径
这两路径的共同部分是 `std::io`,正是完整的第一路径。要将这两路径合并为一条 `use` 语句,我们可在嵌套路径中使用 `self`,如清单 7-20 所示。 这两路径的共同部分是 `std::io`而这正是完整的第一路径。要将这两路径合并为一条 `use` 语句,我们可在嵌套路径中使用 `self`,如清单 7-20 所示。
文件名:`src/main.rs` 文件名:`src/main.rs`
@@ -285,25 +287,23 @@ use std::io::Write;
use std::io::{self, Write}; use std::io::{self, Write};
``` ```
*清单 7-20将清单 7-19 中的路径合并为一个 `use` 语句* <a name="listing_7-20"></a>
**清单 7-20**:合并清单 7-19 中的路径为一条 `use` 语句
行代码会将 `std::io` `std::io::Write` 纳入作用域。 一行会带入 `std::io` `std::io::Write` 作用域。
## 全局操作符,`*` ## 全局运算符导入项目
**The Glob Operator**
如果我们想将某个路径中定义的 *所有* 公开项目都纳入作用域,可以在指定路径后加上 `*` 这个全局操作符:
当我们打算带入定义在路径下的 *所有* 公开项目到作用域时,我们可以指定该路径,后跟 `*` 这个全局运算符:
```rust ```rust
use std::collections::*; use std::collections::*;
``` ```
这条 `use` 语句会 `std::collections` 中定义的所有公开项目引入当前作用域。使用全局操作符时要心!全局会使咱们更难分辨,哪些名称是在作用域中以及程序中使用的名字是在何处定义。 这条 `use` 语句会带入定义在 `std::collections` 的所有公开项目当前作用域。使用全局运算符时要心!全局会使区分哪些名在作用域中以及程序中用的名字何处定义变得更难。此外,当依赖项修改了其定义时,咱们已导入的内容也会改变,例如,当依赖项添加了带有与同一作用域下咱们的某个定义同样名字的定义,那么在咱们更新依赖项后,这可能导致编译器错误
全局操作符通常在测试时使用,以便将所有被测试内容引入 `tests` 模块;我们将在第 11 章 [如何编写测试”](../automated_tests/howto.md#怎样编写测试) 小节中讨论这个问题。全局操作符有时也作前奏模式the prelude pattern的一部分使用:有关该模式的更多信息,请参阅 [标准库文档](https://doc.rust-lang.org/std/prelude/index.html#other-preludes)。 全局运算符通常在测试时使用,以带入所有被测试内容 `tests` 模块;我们将在第 11 章中的 [怎样编写测试”](../automated_tests/howto.md) 小节中讨论这。全局运算符有时也作前奏模式the prelude pattern的一部分有关该模式的更多信息请参阅 [标准库文档](https://doc.rust-lang.org/std/prelude/index.html#other-preludes)。
End End