无论是绝对路径还是相对路径,每次都很麻烦。可以用 use关键字将路径一次性引入作用域,然后调用该路径中的项。

  1. mod front_of_house {
  2. pub mod hosting {
  3. pub fn add_to_waitlist() {}
  4. }
  5. }
  6. use crate::front_of_house::hosting;
  7. pub fn eat_at_restaurant() {
  8. hosting::add_to_waitlist();
  9. hosting::add_to_waitlist();
  10. hosting::add_to_waitlist();
  11. }

在作用域中增加 use 和路径类似于在文件系统中创建软连接(符号连接,symbolic link)。

  1. mod front_of_house {
  2. pub mod hosting {
  3. pub fn add_to_waitlist() {}
  4. }
  5. }
  6. use self::front_of_house::hosting;
  7. pub fn eat_at_restaurant() {
  8. hosting::add_to_waitlist();
  9. hosting::add_to_waitlist();
  10. hosting::add_to_waitlist();
  11. }

创建惯用的 use 路径

为什么上述代码是指定 use crate::front_of_house::hosting,然后在 eat_at_restaurant中调用 hosting::add_to_waitlist,而不是通过指定一直到 use crate::front_of_house::hosting::add_to_waitlist?
是使用 use 将函数引入作用域的习惯用法。要想使用 use 将函数的父模块引入作用域,我们必须在调用函数时指定父模块,这样可以清晰地表明函数不是在本地定义的,同时使完整路径的重复度最小化。
下面展示了将 HashMap结构体引入二进制 crate 作用域的习惯用法:

  1. use std::collections::HashMap;
  2. fn main() {
  3. let mut map = HashMap::new();
  4. map.insert(1, 2);
  5. }

这个习惯用法有个例外,就是使用 use语句将两个具有相同名称的项带入作用域。

  1. use std::fmt;
  2. use std::io;
  3. fn function1() -> fmt::Result {
  4. // --snip--
  5. }
  6. fn function2() -> io::Result<()> {
  7. // --snip--
  8. }

如你所见,使用父模块可以区分这两个 Result 类型。如果我们是指定 use std::fmt::Resultuse std::io::Result,我们将在同一作用域拥有了两个 Result 类型,当我们使用 Result 时,Rust 则不知道我们要用的是哪个。

使用 as 关键字提供新的名称

在类型路径后面,使用 as指定一个新的本地名称或者别名。

  1. use std::fmt::Result;
  2. use std::io::Result as IoResult;
  3. fn function1() -> Result {
  4. // --snip--
  5. }
  6. fn function2() -> IoResult<()> {
  7. // --snip--
  8. }

使用 pub use 重导出名称

使用 use 关键字,将某个名称导入当前作用域后,这个名称在此作用域中就可以使用了,但它对此作用域之外还是私有的。如果想让其他人调用代码,也能正常使用这个名称,可以将 pubuse 合起来使用。这种技术被称为 重导出

  1. mod front_of_house {
  2. pub mod hosting {
  3. pub fn add_to_waitlist() {}
  4. }
  5. }
  6. pub use crate::front_of_house::hosting;
  7. pub fn eat_at_restaurant() {
  8. hosting::add_to_waitlist();
  9. hosting::add_to_waitlist();
  10. hosting::add_to_waitlist();
  11. }

通过 pub use,外部代码现在可以通过新路径 hosting::add_to_waitlist 来调用 add_to_waitlist 函数。如果没有指定 pub useeat_at_restaurant 函数可以在其作用域中调用 hosting::add_to_waitlist,但外部代码则不允许使用这个新路径。

嵌套路径来消除大量的 use 行

  1. // --snip--
  2. use std::cmp::Ordering;
  3. use std::io;
  4. // --snip--
  5. use std::{cmp::Ordering, io};
  1. use std::io;
  2. use std::io::Write;
  3. // --snip--
  4. use std::io::{self, Write};

通过 glob 运算符将所有的公有定义引入作用域

  1. use std::collections::*;