嘉义市网站建设_网站建设公司_Sketch_seo优化
2026/1/2 21:53:21 网站建设 项目流程

一、核心概念铺垫

Rust 模块系统的三大核心关键字:

  1. mod定义模块,建立代码逻辑分组,同时关联对应的文件(Rust 会根据mod声明自动查找同名文件/目录)
  2. pub控制可见性,Rust 模块默认私有(外部模块无法访问),需通过pub暴露模块、函数、结构体等项
  3. use引入模块/项,简化路径书写,避免重复写完整模块路径
  4. 模块与文件的映射规则:
    • 入口文件:二进制工程(src/main.rs)、库工程(src/lib.rs),所有模块必须在入口文件或其子孙模块中声明
    • 同一目录:mod xxx;对应xxx.rs文件
    • 子目录:mod xxx;传统对应xxx/mod.rs(Rust 2015),现代 Rust(2018+)可省略mod.rs,直接嵌套声明

二、单文件内的模块(基础演示)

先从单文件模块入手,理解modpubuse的基础用法。

文件结构

src/ └── main.rs # 唯一文件

代码实现(src/main.rs)

// 1. 定义私有模块 greet(默认私有,仅当前文件可访问)modgreet{// 2. 用 pub 暴露函数(外部可访问)pubfnsay_hello(name:&str){println!("Hello, {}!",name);}// 私有函数(仅 greet 模块内部可访问,外部无法调用)fnsay_goodbye(name:&str){println!("Goodbye, {}!",name);}// 模块内部可调用私有函数pubfngreet_and_leave(name:&str){self::say_hello(name);// self:: 表示当前模块(相对路径)self::say_goodbye(name);}}// 3. 定义数学模块,暴露函数和常量modmath{pubconstPI:f64=3.1415926;pubfnadd(a:i32,b:i32)->i32{a+b}pubfnmultiply(a:i32,b:i32)->i32{a*b}}fnmain(){// 方式1:直接通过 模块名::项 访问(完整路径)greet::say_hello("Alice");greet::greet_and_leave("Bob");println!("10 + 20 = {}",math::add(10,20));println!("PI = {}",math::PI);// 方式2:用 use 引入项,简化后续调用usegreet::say_hello;usemath::{add,PI,multiply};// 批量引入多个项say_hello("Charlie");println!("30 + 40 = {}",add(30,40));println!("5 * 6 = {}",multiply(5,6));println!("PI value: {}",PI);// 方式3:用 use + * 通配符,引入模块下所有公有项(不推荐在工程中大量使用,易命名冲突)usemath::*;println!("7 * 8 = {}",multiply(7,8));}

运行结果

Hello, Alice! Hello, Bob! Goodbye, Bob! 10 + 20 = 30 PI = 3.1415926 Hello, Charlie! 30 + 40 = 70 5 * 6 = 30 PI value: 3.1415926 7 * 8 = 56

三、同一目录下的多文件模块(核心场景)

当代码量增大时,需要将模块拆分到独立文件中,这是最常用的场景。

文件结构

src/ ├── main.rs # 入口文件 ├── greet.rs # greet 模块对应的文件 └── math.rs # math 模块对应的文件

步骤1:编写模块文件(greet.rs & math.rs)

src/greet.rs
// 直接编写模块内容,无需再写 mod greet {}// 公有函数(外部可访问)pubfnsay_hello(name:&str){println!("Hello, {}!",name);}// 公有函数pubfngreet_and_leave(name:&str){// 调用当前模块的私有函数(相对路径,可省略 self::)say_goodbye(name);say_hello(name);}// 私有函数(仅 greet 模块内部可访问)fnsay_goodbye(name:&str){println!("Goodbye, {}!",name);}
src/math.rs
// 公有常量pubconstPI:f64=3.1415926;// 公有函数pubfnadd(a:i32,b:i32)->i32{a+b}// 公有函数pubfnmultiply(a:i32,b:i32)->i32{a*b}// 私有函数(外部无法访问)fndivide(a:f64,b:f64)->f64{ifb==0.0{panic!("Division by zero!");}a/b}

步骤2:入口文件声明并使用模块(main.rs)

// 1. 声明模块:Rust 会自动查找同名 .rs 文件(greet.rs → greet 模块)modgreet;modmath;fnmain(){// 方式1:完整路径访问greet::say_hello("Alice");println!("10 + 20 = {}",math::add(10,20));println!("PI = {}",math::PI);// 方式2:use 引入,简化调用usegreet::greet_and_leave;usemath::{add,multiply,PI};greet_and_leave("Bob");println!("3 * 4 = {}",multiply(3,4));println!("50 + 60 = {}",add(50,60));println!("Circle area (r=2): {}",PI*2.0*2.0);// 错误示例:无法访问私有函数(math::divide 是私有,编译报错)// let _ = math::divide(10.0, 2.0);}

运行结果

Hello, Alice! 10 + 20 = 30 PI = 3.1415926 Goodbye, Bob! Hello, Bob! 3 * 4 = 12 50 + 60 = 110 Circle area (r=2): 12.5663704

四、子目录下的模块(复杂工程场景)

对于大型工程,需要用子目录组织模块(如calculator/add.rscalculator/subtract.rs),分两种实现方式(推荐现代简化方式)。

场景A:传统方式(兼容 Rust 2015,使用 mod.rs)

文件结构
src/ ├── main.rs # 入口文件 └── calculator/ # 子目录(对应 calculator 模块) ├── mod.rs # calculator 模块的入口文件(必须) ├── add.rs # calculator 的子模块 add └── subtract.rs # calculator 的子模块 subtract
步骤1:编写子模块文件(add.rs & subtract.rs)
src/calculator/add.rs
// 公有加法函数pubfnadd(a:i32,b:i32)->i32{a+b}
src/calculator/subtract.rs
// 公有减法函数pubfnsubtract(a:i32,b:i32)->i32{a-b}
步骤2:编写模块入口文件(mod.rs)
// 统一声明 可 外访 子模块(关联 add.rs 和 subtract.rs)pubmodadd;pubmodsubtract;
步骤3:入口文件使用模块(main.rs)
// 1. 声明子目录模块(关联 calculator/mod.rs)modcalculator;fnmain(){// 方式1:完整路径访问(因 mod.rs 导出了子模块,可直接访问)letsum=calculator::add::add(10,20);letdiff=calculator::subtract::subtract(50,15);println!("10 + 20 = {}",sum);println!("50 - 15 = {}",diff);// 方式2:use 引入,简化调用usecalculator::{add,subtract};letsum2=add::add(30,40);letdiff2=subtract::subtract(100,25);println!("30 + 40 = {}",sum2);println!("100 - 25 = {}",diff2);// 优化:直接引入子模块的函数(更简洁)usecalculator::add::addascalc_add;usecalculator::subtract::subtractascalc_sub;println!("5 + 5 = {}",calc_add(5,5));println!("20 - 7 = {}",calc_sub(20,7));}

场景B:现代简化方式(Rust 2018+,无需 mod.rs)

无需创建mod.rs,直接在入口文件嵌套声明模块,更简洁。

文件结构
src/ ├── main.rs # 入口文件 └── calculator/ # 子目录 ├── add.rs # add 模块 └── subtract.rs # subtract 模块
步骤1:子模块文件不变(add.rs & subtract.rs)

同场景A的src/calculator/add.rssrc/calculator/subtract.rs

步骤2:入口文件直接声明嵌套模块(main.rs)
// 1. 嵌套声明模块:直接关联子目录下的文件modcalculator{// 声明并导出子模块(pub mod 让外部可访问)pubmodadd;pubmodsubtract;}fnmain(){// 使用方式与传统方式一致usecalculator::add::add;usecalculator::subtract::subtract;println!("100 + 200 = {}",add(100,200));println!("300 - 150 = {}",subtract(300,150));}

运行结果(两种场景一致)

10 + 20 = 30 50 - 15 = 35 30 + 40 = 70 100 - 25 = 75 5 + 5 = 10 20 - 7 = 13 100 + 200 = 300 300 - 150 = 150

五、补充:模块路径(绝对路径 vs 相对路径)

Rust 支持两种路径访问方式,优先推荐绝对路径(更稳定):

  1. 绝对路径:以crate::开头,从根模块(入口文件)开始查找
    // 在 main.rs 中usecrate::calculator::add::add;// 在 calculator/add.rs 中(访问 math 模块)// pub fn add_and_pi(a: i32, b: i32) -> f64 {// (a + b) as f64 * crate::math::PI// }
  2. 相对路径:以self::(当前模块)、super::(父模块)开头,适用于模块内部
    // 在 calculator/mod.rs 中// self::add 表示当前模块(calculator)下的 add 子模块pubuseself::{add,subtract};// 在 greet.rs 中(若需访问 math 模块,用 super:: 回到父模块(根模块))// pub fn greet_with_pi(name: &str) {// println!("Hello {}, PI is {}", name, super::math::PI);// }

六、常见问题总结

  1. 找不到模块:忘记在入口文件/父模块中用mod 模块名;声明模块(Rust 无法自动发现文件)
  2. 无法访问模块项:未给模块/函数/结构体加pub关键字(默认私有,外部不可访问)
  3. 路径错误:混淆绝对路径(crate::)和相对路径(self::/super::),优先使用绝对路径
  4. 子目录模块无法访问:传统方式未在mod.rs中用pub use导出子模块;现代方式未用pub mod声明子模块

总结

  1. Rust 模块通过mod定义、pub暴露、use引入,文件结构与模块结构一一对应
  2. 同一目录:mod xxx;对应xxx.rs;子目录:传统对应xxx/mod.rs,现代可省略mod.rs
  3. 访问方式:完整路径直接访问、use引入简化访问,支持绝对路径(crate::)和相对路径(self::/super::
  4. 核心原则:模块默认私有,需显式用pub暴露;所有模块必须在入口文件或其父模块中声明

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询