不想再用mod.rs了?试试Rust模块新的命名约定

2,484 阅读3分钟

Rust多模块

前置知识

  • packagecargo new出来的根文件夹就是一个项目包

    • 二进制craetbinary cratecargo new demo
      • 一个至少有一个或多个crate
      • main.rscrate root
    • 库cratelibrary crate:可以和binary crate放在同一个包内,也可以cargo new --lib demo一个单独的包
      • 一个包可以有0-1个crate
      • lib.rscrate root
  • 工作空间workspace:多个项目联合在一起可以组成工作空间

  • 箱子crate:提供多个功能,相当于dll或者作为第三方依赖

  • 货船cargo:包管理工具,要用的第三方依赖就是箱子,传输管理的是货船

  • 关键字pub:公开模块或方法,默认是私有的

  • 关键字use:导入模块到作用域,始终从crate root开始

  • 关键字pub use:导入当前作用域并公开模块或方法

  • 关键字mod:定义或导入模块

  • 关键字super:引用父模块,相当于../

  • 关键字self:引用自身模块,调用同一模块的内容

  • 关键字crate:引用同级模块

1、 在Rust 1.30之前使用mod.rs来定义模块和嵌套子模块

cargo new demo

src\util\bar.rs

pub fn print_src_bar() {
    println!("bar");
}

src\util\foo.rs

pub fn print_src_foo() {
    println!("foo");
}

src\util\mod.rsmod.rs定义的内容编译器会找同级目录的bar.rsbar\mod.rs文件

// 公开模块识别crate
pub mod bar;
pub mod foo;

main.rs:crate root

mod util;

use crate::util::{bar, foo};
fn main() {
    bar::print_src_bar();
    foo::print_src_foo();
}

模块树

image-20240827072042761-1724717977035-1.png

执行cargo run成功调用方法

bar
foo

也可以直接在util\mod.rs里编写方法,比如路由

pub mod bar;
pub mod foo;
// 公开模块才能识别到crate和方法
pub mod routes{
    pub fn routes(){
        println!("routes");
    }
}

main.rs:crate root

mod util;
use crate::util::{ bar, foo };
use crate::util::routes::routes;
fn main() {
    bar::print_src_bar();
    foo::print_src_foo();
    routes();
}

模块树

image-20240827082224381.png

2、 在Rust 1.30之后,直接创建子模块,不需要mod.rs

cargo new demo

src\util\bar.rs

pub fn print_src_bar() {
    println!("bar");
}

src\util\foo.rs

pub fn print_src_foo() {
    println!("foo");
}
  1. main.rs声明``crate`
mod util{
    pub mod bar;
    pub mod foo;
}
use util::bar;
use util::foo;

fn main() {
    bar::print_src_bar();
    foo::print_src_foo();
    println!("main");
}

执行cargo run成功调用方法

bar
foo
main

2. 使用<folder_name>.rs

新建一个src\util.rs

pub mod bar;
pub mod foo;

main.rs

mod util;
use crate::util::bar;
use crate::util::foo;
fn main() {
    bar::print_src_bar();
    foo::print_src_foo();
    println!("main");
}

执行cargo run

bar
foo
main

模块树

image-20240827082425240.png

Rust多模块应用

  • 使用[workspace]使子模块依赖于一个Cargo.toml,共享一个target输出目录

  • 使用cargo new --lib新建子模块,在根目录Cargo.toml添加[workspace]来嵌套子模块

创建父项目

cargo new demo

创建子模块

cargo new --lib application

application\src\util\app_bar.rs

pub fn print_app_bar() {
    println!("app_bar");
}

application\src\util\app_foo.rs

pub fn print_app_foo() {
    println!("app_foo");
}

application\src\lib.rs

pub mod util{
    pub mod app_bar;
    pub mod app_foo;
}

如果有依赖要导入到当前模块中使用

// 在lib.rs添加
pub use sea_orm_migration::prelude::*;
// 在要使用的crate中添加
use sea_orm_migration::prelude::*;

在父项目根目录的Cargo.toml添加

[workspace]
members = [".","application"]
[dependencies]
application = {path = "application"}

src\main.rs

use application::util::app_bar;
use application::util::app_foo;
fn main() {
    app_bar::print_app_bar();
    app_foo::print_app_foo();
    println!("main");
}

执行cargo run

app_bar
app_foo
main

新建其他模块同样的套路,cargo new --lib 模块名,父项目的Cargo.toml会自动添加

[workspace]
members = [".","application", "模块名"]

要使用哪个模块的方法就在哪个模块的Cargo.toml添加[dependencies]并指定路径path,比如实体定义在entity模块中,在serviceCargo.toml添加

[dependencies]
entity = { path = "../entity" }