运维开发网

深入解释Rust模块的用法

运维开发网 https://www.qedev.com 2022-08-31 21:15 出处:网络
很多时候,我们写的代码需要按模块组织,因为我们无法将大量的代码都写在一个文件上,那样不容易维护,下面这篇文章主要给大家介绍了关于Rust模块使用方式的相关资料,需要的朋友可以参考下

很多时候,我们写的代码需要按模块组织,因为我们无法将大量的代码都写在一个文件上,那样不容易维护,下面这篇文章主要给大家介绍了关于Rust模块使用方式的相关资料,需要的朋友可以参考下


前言

这篇文章适合刚开始学习rust的学生,用来帮助他们理解rust模块是如何相互引用的。本文试图用很少的代码来演示,即使你之前不了解rust,也可以很熟悉。用的时候可以有印象。

如果你以前不知道rust,你只需要知道:货物依赖管理工具,类似于npm。Cargo使用文件放置约定,即文件名是模块名。Crate- container是一个功能包,类似于npm包。

本文讨论的场景是,当代码被拆分成文件,从一个项目中不同程度的模块中抽出时,往往需要将另一个模块的部分代码引入到一个文件中。在javascript中,我们可以通过导入和导出来使用其他模块的代码。在这个过程中,我们只需要关心导入路径是否正确。

export const name= xx import lodash from './lodash'

在rust中,模块不再通过文件路径引入,而是通过cargo和约定的模块声明构建模块树,然后通过use关键字使用。但是rust的文档中文件拆分和模块使用的例子并不是太详细,所以我们参考了一些公开的板条箱组织方法进行了梳理。


模块声明amp;使用

假设我们要实现一个加法模块,提供给其他地方。我们可以通过以下三种方式进行组织

Cargo使用文件放置约定,因此模块搜索基于src目录中的rs文件或目录,并且只有一级搜索。嵌套文件夹中的rs文件不能被其他文件直接使用。


方法一:直接在根文件下声明 add.rs

我们可以在src下添加一个模块名相同的文件,cargo可以识别添加的模块。

├── Cargo.lock├── Cargo.toml├── src│ ├── add.rs│ ├── lib.rs


方法二:声明add文件夹,文件夹下包含 mod.rs

如果模块是一个文件夹,必须有一个mod.rs文件。这类似于javascript的index.js。Cargo还是能认出这是add模块。

├── Cargo.lock├── Cargo.toml├── src│ ├── add│ │ ├── mod.rs│ ├── lib.rs

假设我们的代码如下,它位于add.rs或add/mod.rs文件中

pub fn add_fn(a: i32, b: i32) -gt; i32 { a + b}

然后在lib.rs中,我们可以用下面的方式调用我们的add模块

// 声明模块并引用模块内的函数mod add;pub use crate::add::add_fn;pub fn test_lib() { add_fn(1,2);}


方法三:add.rs和add文件夹同时存在

这样的目录结构如下所示

├── Cargo.lock├── Cargo.toml├── src│ ├── add│ │ └── add_m.rs│ ├── add.rs // index.js│ ├── lib.rs

Add.rs负责入口模块的导入导出,其他相关模块存放在Add文件夹中。这个index.js类似于javascript,统一导出许多其他模块。与上面不同的是,这里的导入使用mod关键字拆分模块;

该文件的内容如下所示

添加rs

pub mod add_m;// 类似于 export * from './validate; export * from './helper'

add/add_m.rs

pub fn add_fn(a: i32, b: i32) -gt; i32 { a + b}

图书馆

mod add;pub use crate::add::add_m::add_fn;pub fn test_lib() { add_fn(1,2);}

以上三种方法应该是前两种,第二种在大型项目中更合理,可以更好的组织文档。那么在一个模块文件夹下拆分多个模块文件时,如何调用相邻的文件呢?


同模块相邻文件引用

我们调整目录结构如下

├── Cargo.lock├── Cargo.toml├── src│ ├── add│ │ ├── mod.rs│ │ ├── print.rs│ │ └── user.rs // user会调用print的方法│ ├── lib.rs

在添加模块下有更多的打印和用户。用户调用打印方法。

print.rs

pub mod my_print { pub fn print_hello() { println!( hello ) }}// 这里的pub mod 可以简单理解为ts的declare module ,里面是module的可用属性// declare module my_print {// export function print_hello(): string;// }

用户. rs

use super::print::my_print;pub fn hello_user() { my_print::print_hello();}pub struct User { pub name: String,}

使用super关键字可以交叉引用同一模块下的文件。

现代rs

// mod.rs为入口文件, 下面用mod声明会先去同文件夹下查找同名文件,如果没有则看是否有满足条件 的同名文件夹// 例如 add 文件夹下没有print.rs 则查找是否有print文件夹并且文件夹下有mod.rs。mod print;mod user;// 因为是同一个模块文件夹下,并且在入口文件使用,所以这里应selfpub use self::user::hello_user;pub use self::user::User;pub mod add_fn { // use super::*; 如果有这行,则下面不用每次调用super pub fn add(a: i32, b: i32) -gt; i32 { // 注意这里super关键字,因为hello_user是在另一个模块声明的,模块间不能直接调用所以需要使用super来从模块根进行查找调用 super::hello_user(); let value = super::User { name: String::from( Rust ), }; println!( user name {} , value.name); a + b }}pub fn test_out_ref() { // 这里不在需要super因为不在mod内定义 hello_user();}


不同模块引用

我们添加了一个新的模块multip,它返回两个数相乘的结果。目录结构如下

├── Cargo.lock├── Cargo.toml├── src│ ├── add│ │ ├── mod.rs│ │ ├── print.rs│ │ └── user.rs // user会调用print的方法│ ├── multip // ------- 新增这个模块│ │ ├── mod.rs法│ ├── lib.rs

多种型号

pub fn res_multip(a: i32, b: i32) -gt; i32 { a * b}

假设add文件引入了multip

mod print;mod user;pub use self::user::hello_user;pub use self::user::User;// 新增下面这行use crate::multi::multip;

因此您可以使用另一个模块的内容。当然,其他模块也以同样的方式相互引用。


小结

总的来说,rust的模块用法比较简单。由于官方文档在模块拆分和组织上没有给出完美的解释,对于刚从js转到rust的同学来说可能会有点不适应。通过前面的内容,使用方式已经梳理的很清楚了。希望能对有需要的同学有所帮助。

关于Rust模块的用法,这篇文章就讲到这里。关于Rust模块使用的更多信息,请搜索源搜网之前的文章或者继续浏览下面的相关文章。

0

精彩评论

暂无评论...
验证码 换一张
取 消