Skip to content

G.MOD.01 导入模块中的类型或函数时,应避免直接使用通配符

【级别】 建议

【描述】

使用通配符导入会污染命名空间,比如导入相同命名的函数或类型。为了避免这种情况,使用导入的类 型或函数时需要带模块名前缀。有个例外,当一个 crate 提供了 prelude 时,可以用 prelude::*

对于标准库中,很多人都熟知的类型 ,比如 Arc/ Rc/ Cell/ HashMap 等 , 可以导入它们直接使用。

但是对于可能引起困惑的函数,比如 std::ptr::replacestd::mem::replace ,在使用它们的时 候,就必须得带上模块前缀。

使用一些第三方库中定义的类型或函数,也建议带上 crate 或模块前缀。如果太长的话,可以考虑使用 astype 来定义别名。

以上考虑都是为了增强代码的可读性、可维护性。

【反例】

Rust
use std::sync::Arc; 
use std::ptr::*;

fn main() {
  let foo = Arc::new(vec![1.0, 2.0, 3.0]); // 直接使用 Arc let a = foo.clone();

  let mut rust = vec!['b', 'u', 's', 't'];

  let b = unsafe {
    // 不符合
    // 不知道 `replace` 是来自 `std::ptr` 还是 `std::mem` 模块
    replace(&mut rust[0], 'r') 
  };
}

【正例】

Rust
use std::sync::Arc; 
use std::ptr;

fn main() {
let foo = Arc::new(vec![1.0, 2.0, 3.0];
let a = foo.clone();


let mut rust = vec!['b', 'u', 's', 't'];

let b = unsafe {
    // 符合
    // 需要带上 ptr 前缀,因为 `std::mem::replace` 也有同样的效果
    ptr::replace(&mut rust[0] 
  };
}