rust中mod的使用

在一个crate中,往往是多文件组成的,rust中的多文件,采用mod管理。

同级目录下的mod

假如有以下目录:

其中mod_same_level.rs和main.rs在同一个目录下,mod_same_level.rs中定义了一个函数:

pub fn foo(){
    println!("Get called at same level");
}

注意该函数被pub修饰,可以被外部访问到。

在main.rs中的使用方法如下:

mod mod_same_level;

use mod_same_level as msl;
use mod_same_level::foo;
use mod_same_level::foo as poo;

fn main() {
    // use mod at the same level
    mod_same_level::foo();
    msl::foo();
    foo();
    poo();
}

代码中四种调用函数的结果都是一样的,注意的点为:

  • 先用mod mod_same_level引入mod_same_level.rs文件,类似于import
  • 可以直接使用mod_same_level::foo()的方式调用,也可以结合use的方式使用。use一般用于起别名,或者减少代码中的前缀,比如use mod_same_level::foo,就可以直接在代码中调用foo(),而不用写一长串mod_same_level::foo()

子目录下的mod

假设我们有一个mod目录如下:

·其中inner_mod_private.rs中的函数没有定义为pub,则为private:

fn inner_foo(){
    println!("Get called at inner mod private");
}

代表着只能在inner_mod_prviate.rs文件中访问。其他任何地方的文件都不能被访问到,包括mod_folder/mod.rs,因此这种没有被pub修饰的函数,不可能作为导出接口。

而inner_mod_public.rs中的函数定义为pub,则可以被外部其他文件访问:

pub fn inner_foo(){
    println!("Get called at inner mod public");
}

pub fn inner_poo(){
    println!("Get called at inner mod public");
}

但实际开发时,往往会通过mod_folder/mod.rs文件再次统一封装的对外接口,把所有作用域为pub的接口进行管理。比如:

  1. 导出整个子mod。

在mod.rs中这样写,意味着导出inner_mod_public.rs文件中所有pub函数:

pub mod inner_mod_public;

则在main.rs这样调用时正确的:

mod mod_folder;

fn main() {
    mod_folder::inner_mod_public::inner_foo();
    mod_folder::inner_mod_public::inner_poo();
}
  1. 导出子mod中部分pub函数

也可以导出指定的函数,比如mod.rs中这样写:

mod inner_mod_public;

pub use inner_mod_public::inner_foo;

第一行把inner_mod_public作用域设置为private,第二行把inner_foo函数设置为pub,因此在main.rs中只能访问inner_foo,不能访问inner_poo:

mod mod_folder;
fn main() {
    mod_folder::inner_foo();
}

使用任意目录的mod

假如有以下目录:

sub_mod_folder_a/mod.rs中,想调用sub_mod_folder_b中的函数怎么办呢?

使用mod路径来调用,这样写:

use crate::mod_folder::sub_mod_folder_b;
pub fn foo(){
    sub_mod_folder_b::foo();
}

这里的crate::mod_folder::sub_mod_folder_b就是mod路径。crate指的就是bin或者lib的入口。要注意这里用的是use关键字,而不是mod,说明mod已经被包含进crate中了。因此,这样写的前提就是:

  • mod_folder已经被main.rs引入了,也就是在main.rs中,有这样的代码:
mod mod_folder;
  • sub_mod_folder_b已经被mod_folder引入了,在mod_folder/mod.rs中,有这样的代码:
pub mod sub_mod_folder_b;

以此类推,只要任意一个mod被引入进了crate中,就可以通过crate::any_mod这样的路径被使用。

pub可见性

首先要明确一点,不设置pub的时候,则该成员为private,private对本mod都可见,对外都不可见。

然后可以通过pub关键字,设置pub成员对指定的mod可见,比如:

// 对外部所有模块可见
pub fn function() {
    println!("called `my_mod::nested::function()`");
}
        
// 使用 `pub(in path)` 语法定义的函数只在给定的路径中可见。
// `path` 必须是父模块(parent module)或祖先模块(ancestor module)
pub(in crate::my_mod) fn public_function_in_my_mod() {
    print!("called `my_mod::nested::public_function_in_my_mod()`, that\n > ");
    public_function_in_nested()
}

// 使用 `pub(self)` 语法定义的函数则只在当前模块中可见。
pub(self) fn public_function_in_nested() {
    println!("called `my_mod::nested::public_function_in_nested");
}

// 使用 `pub(super)` 语法定义的函数只在父模块中可见。
pub(super) fn public_function_in_super_mod() {
    println!("called my_mod::nested::public_function_in_super_mod");
}

虽然pub(self)和private都对外不可见,但二者也有区别:

  • pub(self)对子模块可见
  • private对子模块不可见


发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

About Me

一位程序员,会弹吉他,喜欢读诗。
有一颗感恩的心,一位美丽的妻子,两个可爱的女儿
mail: geraldlee0825@gmail.com
github: https://github.com/lisuxiaoqi
medium: https://medium.com/@geraldlee0825