6

Rust的模块系统初探

 2 years ago
source link: https://zhuanlan.zhihu.com/p/46487796
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

Rust的模块系统初探

野生程序员

学习一门编程语言,知道如何引用外部的文件或者说模块系统是比较重要的一点,PHP用autoload机制,C有经典的include。最近写 wslexe 的时候,因为原作者用的 rust,所以就简单学习了一下。但是 rust 的模块文档是从顶部设计开始写的,很多概念,有些复杂,这里写一个应用导向的学习笔记。

引入文件

首先,让我们初始化一个项目。

mkdir rustmod
cd rustmod
cargo init

我们得到了下面这样的基础项目结构

rustmod
├── Cargo.toml
└── src
    └── main.rs

main.rs里面只有一个简单的输出的‘hello world’的main函数。我们新增一个functions.rs文件,将生成字符串的过程做成一个函数,供main函数调用。

//file: rustmod/src/functions.rs
pub fn hello(name: String) -> String {
    format!("Hello, {}!", name)
}

functions.rs就成为了一个单文件模块,rust 中称为mod,模块的名称就是文件的名称。模块内部的函数,只能在模块内部使用,如果要在模块外调用,需要用pub关键词,显式声明函数可在外部使用,我自己把这个叫导出函数。

下面我尝试在main函数中使用functions模块。使用的方式很简单,只要在使用前声明一下模块就可以了。声明模块使用mod关键字。使用模块内函数的时候,需要用::进行调用。

mod functions;//声明模块
fn main() {
    let s = functions::hello("World".to_string());
    println!("{}", s)
}

如果去掉函数前的pub关键词,编译器就会报错。

error[E0603]: function `hello` is private

模块的嵌套

rust 除了一个文件作为一个模块之外,还持支模块的嵌套。嵌套的方式,有两种。

第一种是在一个文件内,用mod关键字定义子模块。比如,我修改functions.rs

//file: rustmod/src/functions.rs
pub mod util {
    pub fn hello(name: String) -> String {
        format!("Hello, {}!", name)
    }
}

同样,模块也是私有的,要在外部调用也需要pub关键字修饰。对应的main函数就要改为

//file: rustmod/src/main.rs
mod functions;
fn main() {
    let s = functions::util::hello("World".to_string());
    println!("{}", s)
}

第二种形式,是用文件夹来组织模块。文件夹的名字是模块的名字,rust 会去寻找文件夹下面的mod.rs作为模块的主文件,可以在里面写任意的 rust 代码,不过大多数时候用来输出目录内的子模块。我们来新建一个util文件夹,作为一个工具库的模块,修改项目结构

rustmod
├── Cargo.toml
└── src
    ├── main.rs
    └── util
        ├── functions.rs
        └── mod.rs

mod.rs输出functions模块。同样也需要用pub关键词修饰,否则就只是mod.rs文件内的私有子模块。

//file: rustmod/src/util/mod.rs
pub mod functions;

修改main.rs中的调用

//file: rustmod/src/main.rs
mod util;
fn main() {
    let s = util::functions::util::hello("World".to_string());
    println!("{}", s)
}

总结

rust 的模块由mod关键字和文件系统两者结合定义。mod关键字用来声明一个模块的名字,模块的内容或直接以mod NAME {MOD CONTENT}的形式书写,或根据严格的规则查找对应源文件。文件查找规则有以下几点:

  1. 查询声明模块的文件所在目录中对应模块名字的NAME.rs文件,如果有就作为模块使用。
  2. 查询声明模块的文件所在目录中对应模块名字NAME的文件夹,并且文件夹内有mod.rs文件,如果有就以mod.rs文件作为模块使用。
  3. 上面的规则都可以互相嵌套。

我尝试了在src目录下,同时存在util.rsutil文件夹,编译的时候报错

error[E0584]: file for module `util` found at both util.rs and util/mod.rs

所以还有第四条规则:

  1. 在同一层级不能同时存在文件夹和文件类型的模块,否则会名字冲突。

原文链接:

Rust的模块系统初探 | Mirror Lake​www.jswh.me


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK