无论是绝对路径还是相对路径,每次都很麻烦。可以用 use
关键字将路径一次性引入作用域,然后调用该路径中的项。
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
use crate::front_of_house::hosting;
pub fn eat_at_restaurant() {
hosting::add_to_waitlist();
hosting::add_to_waitlist();
hosting::add_to_waitlist();
}
在作用域中增加 use 和路径类似于在文件系统中创建软连接(符号连接,symbolic link)。
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
use self::front_of_house::hosting;
pub fn eat_at_restaurant() {
hosting::add_to_waitlist();
hosting::add_to_waitlist();
hosting::add_to_waitlist();
}
创建惯用的 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 作用域的习惯用法:
use std::collections::HashMap;
fn main() {
let mut map = HashMap::new();
map.insert(1, 2);
}
这个习惯用法有个例外,就是使用 use
语句将两个具有相同名称的项带入作用域。
use std::fmt;
use std::io;
fn function1() -> fmt::Result {
// --snip--
}
fn function2() -> io::Result<()> {
// --snip--
}
如你所见,使用父模块可以区分这两个 Result 类型。如果我们是指定 use std::fmt::Result
和 use std::io::Result
,我们将在同一作用域拥有了两个 Result 类型,当我们使用 Result 时,Rust 则不知道我们要用的是哪个。
使用 as 关键字提供新的名称
在类型路径后面,使用 as
指定一个新的本地名称或者别名。
use std::fmt::Result;
use std::io::Result as IoResult;
fn function1() -> Result {
// --snip--
}
fn function2() -> IoResult<()> {
// --snip--
}
使用 pub use 重导出名称
使用 use 关键字,将某个名称导入当前作用域后,这个名称在此作用域中就可以使用了,但它对此作用域之外还是私有的。如果想让其他人调用代码,也能正常使用这个名称,可以将 pub
和 use
合起来使用。这种技术被称为 重导出。
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();
hosting::add_to_waitlist();
hosting::add_to_waitlist();
}
通过 pub use,外部代码现在可以通过新路径 hosting::add_to_waitlist
来调用 add_to_waitlist
函数。如果没有指定 pub use
,eat_at_restaurant
函数可以在其作用域中调用 hosting::add_to_waitlist
,但外部代码则不允许使用这个新路径。
嵌套路径来消除大量的 use 行
// --snip--
use std::cmp::Ordering;
use std::io;
// --snip--
use std::{cmp::Ordering, io};
use std::io;
use std::io::Write;
// --snip--
use std::io::{self, Write};
通过 glob 运算符将所有的公有定义引入作用域
use std::collections::*;