Use 声明
语法:
Use声明 :
use
Use树;
Use树 :
(简单路径?::
)?*
| (简单路径?::
)?{
(Use树 (,
Use树 )*,
?)?}
| 简单路径 (as
( 标识符 |_
) )?
use 声明 会创建一个或多个局部的名称绑定,和某个其他路径有相同的含义。
通常,use
声明用于缩短引用模块条目所需的路径。
这些声明通常出现在 模块 和 块 中,通常在顶部。
Use 声明支持许多方便的快捷方式:
- 使用类似通配符的花括号语法同时绑定具有相同前缀的路径列表,例如
use a::b::{c, d, e::f, g::h::i};
。 - 使用
self
关键字同时绑定具有相同前缀和共同父模块的路径列表,例如use a::b::{self, c, d::e};
。 - 重新将目标名称绑定为新局部名称,使用语法
use p::q::r as x;
。这也可以与前两个功能一起使用:use a::b::{self as ab, c as abc}
。 - 使用星号通配符语法绑定与给定前缀匹配的所有路径,例如
use a::b::*;
。 - 多次嵌套前面的功能组合,例如
use a::b::{self as ab, c, d::{*, e::f}};
。
以下关于 use
声明的例子:
use std::collections::hash_map::{self, HashMap}; fn foo<T>(_: T){} fn bar(map1: HashMap<String, usize>, map2: hash_map::HashMap<String, usize>){} fn main() { // use 声明也可以存在于函数中 use std::option::Option::{Some, None}; // 相当于 'foo(vec![std::option::Option::Some(1.0f64), std::option::Option::None]);' foo(vec![Some(1.0f64), None]); // `hash_map` 和 `HashMap` 都在作用域内。 let map1 = HashMap::new(); let map2 = hash_map::HashMap::new(); bar(map1, map2); }
use
可见性
和其他条目一样,默认情况下, use
声明只在其所在的模块中可见。
如果在 use
声明前加上 pub
关键字,那么 use
声明就是公开的。
这样的 use
声明就可以用来 重新导出 一个名称。
公开的 use
声明可以将某个公开名称重定向到一个不同的目标:甚至是定义在不同模块中私有的规范路径。
如果重定向形成循环或无法消除歧义,会导致编译时错误。
一个重新导出的例子:
mod quux { pub use self::foo::{bar, baz}; pub mod foo { pub fn bar() {} pub fn baz() {} } } fn main() { quux::bar(); quux::baz(); }
在这个例子中,模块 quux
重新导出了在 foo
中定义的两个公开名称。
use
Paths
注意: 本节内容不完整。
以下是一些关于 use
声明能够和不能够正常工作的例子:
#![allow(unused_imports)] use std::path::{self, Path, PathBuf}; // good: std 是 crate 名称 use crate::foo::baz::foobaz; // good: Foo 位于 crate 的根 mod foo { pub mod example { pub mod iter {} } use crate::foo::example::iter; // good: foo 位于 crate 的根 // use example::iter; // bad 在 2015 版次: 相对路径不允许没有 `self` ; 2018 版good use self::baz::foobaz; // good: Self 引用模块 'foo' use crate::foo::bar::foobar; // good: foo 位于 crate 的根 pub mod bar { pub fn foobar() { } } pub mod baz { use super::bar::foobar; // good: Super 指的是模块 foo pub fn foobaz() { } } } fn main() {}
版次差异: 在 2015 版本中,
use
路径还允许访问 crate 根中的条目。 使用上面的例子,以下use
路径在 2015 版中可以使用但在 2018 版中无法使用:mod foo { pub mod example { pub mod iter {} } pub mod baz { pub fn foobaz() {} } } use foo::example::iter; use ::foo::baz::foobaz; fn main() {}
2015 版不允许
use
声明引用 extern 预定义 。因此,在 2015 中,仍需要使用extern crate
声明来引用use
声明中的外部 crate。从 2018 版开始,use
声明可以像extern crate
一样指定一个外部 crate 依赖。在 2018 版本中,如果在作用域内存在与外部 crate 相同的名称,则使用该 crate 名称需要在前面加上
::
以明确选择 crate 名称。这是为了保留与未来潜在更改的兼容性。// use std::fs; // Error, 有歧义 use ::std::fs; // 从 std crate 导入,而不是下面的模块。 use self::std::fs as self_fs; // 导入下面的模块。 mod std { pub mod fs {} } fn main() {}
下划线导入
条目可以通过在路径前加一个下划线的形式 use path as _
导入,而不必绑定到一个名字。
这种方法特别适用于导入 trait ,以便可以使用 trait 方法而不必导入该 trait 的符号,例如,如果该 trait 的符号可能与另一个符号发生冲突。
另一个例子是链接外部 crate ,也不导入其名称。
星号通配符将导入以不可命名的形式 _
导入的条目。
mod foo { pub trait Zoo { fn zoo(&self) {} } impl<T> Zoo for T {} } use self::foo::Zoo as _; struct Zoo; // 下划线导入避免了与此条目的名称冲突。 fn main() { let z = Zoo; z.zoo(); }
独特的、无法命名的符号是在宏展开后创建的,因而宏可以安全地创建 _
导入的多个引用。例如,下面的代码将不会出错:
#![allow(unused)] fn main() { macro_rules! m { ($item: item) => { $item $item } } m!(use std as _;); // 展开为: // use std as _; // use std as _; }