• 模块与包

包(crate)

Rust的crate在于其他语言中被称为“package”或“library”。Rust的crate是一个独立的可编译单元。

使用cargo既可创建一个crate,具体参见《Rust简介 - > Cargo》

值得注意:一个工程下可以包含多个crate。

crate包内可以有一个main.rs文件,其中包含main函数。也就是说,若crate拥有main函数,则该crate被编译后即可运行。

模块(module)

Rust中使用mod在一个文件中定义一个模块,或引用另外一个文件中的模块。

关于模块的特性:

  1. 每个 crate 中,默认实现了一个隐式的 根模块(root module);
  2. 模块可以嵌套;
  3. 模块的命名风格也是 lower_snake_case,跟其它的 Rust 的标识符一样;
  4. 模块中可以写任何合法的 Rust 代码;

定义一个模块

例:定义模块。在lib.rs 中,添加代码。

mod aaa {
    const X: i32 = 10;

    fn print_aaa() {
        println!("{}", 42);
    }
}

嵌套的模块

mod aaa {
    const X: i32 = 10;

    fn print_aaa() {
        println!("{}", 42);
    }

    mod bbb {
        fn print_bbb() {
            println!("{}", 37);
        }
    }
}

树状嵌套的mod。

mod aaa {
    const X: i32 = 10;

    fn print_aaa() {
        println!("{}", 42);
    }

    mod bbb {
        fn print_bbb() {
            println!("{}", 37);
        }
    }
}

mod ccc {
    fn print_ccc() {
        println!("{}", 25);
    }

}

可以看到使用mod在一个文件内可以以树形形式定义模块。

在外部文件定义模块

在abc.rs文件中

pub fn print_abc() {
    println!("abc");
}

在main.rs模块中

mod abc;

use abc::print_abc;

fn main () {
    print_abc();
}

abc.rs中没有使用mod xxx {}这样包裹起来。使用mod xxx;相当于把xxx.rs文件用mod xxx {}包裹起来了。

模块可见性

默认模块不对包外暴露模块以及模块内的函数和结构体。使用pub,使其对外暴露。

  1. 公有的可被父级模块访问。
  2. 私有以及当前模块与子模块访问。
  3. 同级项可以相互访问。
mod outermost {
    pub fn middle_function() {}

    fn middle_secret_function() {}

    mod inside {
        pub fn inner_function() {}

        fn secret_function() {}
    }
}

// try_me可识别到outermost
fn try_me() {
    outermost::middle_function();   // 访问同级公有函数
    outermost::middle_secret_function();   // 编译错误,不可访问私有函数。
    outermost::inside::inner_function();   // 编译错误,不可访问私有模块的公有函数。
    outermost::inside::secret_function();  // 编译错误,不可访问私有模块的私有函数。
}

函数的调用

模块内的可访问函数方式:

  • 模块名::函数名
  • 模块名::结构体名

详解use

例:

pub mod a {
    pub mod series {
        pub mod of {
            pub fn nested_modules() {}
        }
    }
}

use a::series::of::nested_modules;

fn main() {
    nested_modules();
    // 否则要这样调用:a::series::of::nested_modules();  非常麻烦。
}

例:

enum TrafficLight {
    Red,
    Yellow,
    Green,
}

use TrafficLight::{Red, Yellow};

fn main() {
    let red = Red;
    let yellow = Yellow;
    let green = TrafficLight::Green;  // 编译不通过
}

例:

enum TrafficLight {
    Red,
    Yellow,
    Green,
}

use TrafficLight::*;  // 引入TrafficLight中所有元素

fn main() {
    let red = Red;
    let yellow = Yellow;
    let green = Green;
}

使用super访问模块

访问模块与访问文件是一致的,都有两种方式:

  • 绝对路径访问
  • 相对路径访问

super表示父包。super关键字类似于文件系统用于表示相对路径的..

来看一个场景,如下app模块中,service模块的call方法希望访问client模块的connect方法。

mod app {

    mod client {
        pub fn connect() {
            println!("connecting!")
        }
    }

    mod service {
        fn call() {
            // 尝试调用app::client::connect();
        }
    }

}

使用绝对路径方式访问:use后面跟函数的全路径。

mod app {

    mod client {
        pub fn connect() {
            println!("connecting!")
        }
    }

    mod service {
        // 相当于使用全路径
        use app::client::connect;

        fn call() {
            connect();
        }
    }
}

使用相对路径方式访问:使用super表示父包。

mod app {

    mod client {
        pub fn connect() {
            println!("connecting!")
        }
    }

    mod service {
        // 相当于使用相对路径
        use super::client::connect;

        fn call() {
            connect();
        }
    }
}

工程中的包定义

Rust中包可以由一直更加美观的方式定义,即每个目录定义为一个mod。即,

  • 目录名作为包名。
  • 目录下通过mod.rs文件说明该目录为包。
  • mod.rs中为此包暴露的方法与子包。

例:crate包的名称为test-lib。其中有若干个包。package1包内有package2包与package3包,另外package1包有pub fn1函数,fn2函数。

   test-lib/
        |----src/
              |----lib.rs
              |----package1/
                      |----mod.rs
                      |----package2/
                              |----mod.rs
                      |----package3 
                              |----mod.rs

这里可以直接参考Rust实际工程:https://github.com/pingcap/tikv/blob/master/src/lib.rs

results matching ""

    No results matching ""