Rust 模块文件配置

2022-04-16 language rust

简介

在 Rust 中包含了 Package、Crate、Module 三层:

  • Package 通过 Cargo 创建的工程就是一个包,目录下包含了一个 Cargo.toml 文件。
  • Crate 树状结构保存,用来编译二进制文件,包括了可执行文件、库等。
  • Module 类似于 Java 中的类,采用层级结果,同样对应文件系统目录层级,通过 :: 分割。

模块分成了公开和私有两种控制,使用通过 use 引用,标准库可以参考 Crate std 中的内容。

示例

其中 Cargo.toml 配置文件如下。

[package]
name = "foobar"
version = "0.1.0"
edition = "2021"

[dependencies]
random = "0.14.0"

修改 src/main.rs 文件如下。

fn main() {
    println!("Got random {}", rand::random());
}

这里的 rand 可以全局直接使用,无需通过 use 方式引入,不过可以通过 use rand::random; 方式引入到主模块,后续直接使用 random() 函数即可。

简单来说,use 的唯一目的是将符号带入命名空间,让符号使用更加简短。

目录结构

包可以最多包含一个库 crate 以及任意多个二进制 crate,默认分别将 src/lib.rssrc/main.rs 作为 crate 的根,其它二进制包的根放在 src/bin 目录下,而且允许使用目录。如果要使用多个库,可以使用 Workspace 进行管理。

在使用时,可以通过 crate super 引用。

project/
 |-Cargo.toml
 `-src/               crate
   |-main.rs           |
   |-config.rs         |-config
   |-pages/            |-pages
   | |-hello.rs        | |-hello
   | `-login.rs        | `-login
   |-pages.rs          |-pages
   |-routes/           |-routes
   | |-mod.rs          | |
   | |-health.rs       | |-health
   | `-user.rs         | `-user
   `-models/           |-models
     |-mod.rs            |
     `-user.rs           `-user

pages.rs 中,可以通过如下方式直接引用,然后就可以使用其内部的实现了。

mod hello;
mod login;

use hello::*;
use login::*;

模块

类似于 C++ 中的 namespace,通过 mod 声明,默认所有的函数、结构体、枚举、常量等都是私有的,可以通过 pub 将其变为公有。子模块可以通过 super 访问父模块中的所有代码,包括私有代码,而反之不可以。

模块可以放在同一文件、同一目录下,如上,在 main.rs 中可以通过 mod config 方式引用。另外,对于底层目录,可以通过 mod.rs 配置。

同文件

最外层模块不需要设置为 pub 就可以访问,但是内部的实现就需要指定访问权限。

use crate::foo::hi; // 调用路径简化

mod foo {
    pub fn hello() {
        println!("Hello World!");
    }
    fn secret() {
        println!("Hi world!");
    }
    pub mod hi {
        pub fn say() {
            super::secret(); // 可以调用父模块的私有函数
        }
    }
}

fn main() {
    foo::hello();        // 相对路径
    crate::foo::hello(); // 绝对路径

    foo::hi::say();

    hi::say();
}

也可以在模块内通过 pub use 的方式重新导出,如果限制当前 crate 使用,那么就可以配置为 pub(crate) 即可。

常用技巧

依赖库

通常在 src/lib.rs 中引用不同的包,例如上述目录结构中可以使用如下方式。

pub mod errors;

pub use client::Client;

多个二进制

编译过程中会默认查找 src/lib.rssrc/main.rs 文件进行编译,默认将 src/bin 目录下的 xxx.rs 文件编译成 xxx 二进制,如果是其它目录,也可以在 Cargo.toml 中通过如下方式指定。

[[bin]]
name ="daemon"
path ="src/daemon/bin/main.rs"

[[bin]]
name ="client"
path ="src/client/bin/main.rs"