Rust编程:模块与路径的使用指南
立即解锁
发布时间: 2025-09-04 01:46:28 阅读量: 288 订阅数: 17 AIGC 


Rust重构实战指南
### Rust编程:模块与路径的使用指南
#### 1. Rust代码中的特殊元素
在Rust编程里,有一些特殊的工具和概念。比如Bindgen,它能为C和C++代码生成Rust绑定。构建脚本则允许开发者编写在编译时运行的Rust代码。`include!` 能在编译时将文本文件插入到Rust源代码文件中,并将其解释为Rust代码。
同时,并非所有的 `extern "C"` 函数都需要 `#[no_mangle]`。重新借用可以让我们把原始指针当作标准的Rust引用。`.offset_from` 可以获取两个指针之间的字节差。`std::slice::from_raw_parts` 能从指针和长度构建一个连续内存块的视图。
Cargo使用路径依赖来包含本地机器上的包,而不是从crates.io上下载的包。包可以编译成 `rlib`(供Rust使用)和 `cdylib`(供C使用)。当将一个项标记为 `pub` 时,编译器会期望其公共API中的所有类型也都是 `pub` 的。Bindgen会自动为C位域创建 `get_` 和 `set_` 函数。切片是对一块内存区域的连续借用视图,`.as_ptr` 返回切片中第一个元素的指针,`.offset` 返回在连续块中距离基指针N个元素的指针。`std::mem::size_of` 相当于C语言中的 `sizeof`,`std::ptr::copy_nonoverlapping` 相当于 `memcpy`。
#### 2. Rust的模块系统
大多数编程语言都有将代码分组的功能,Rust也不例外,它拥有强大的模块系统,可以用来组织包。在Rust中,模块是容纳项的容器,项可以是函数、结构体、枚举或类型等。例如,我们从标准库的 `std` 包的 `fmt` 模块中导入过 `Display` 特性,`std` 是Rust标准库,`fmt` 模块包含用于文本格式化的项,如 `Display` 和 `Debug` 特性。
下面通过一个简单的示例来看看如何使用模块。假设我们要编写一个程序,获取用户的名字,然后向用户打招呼和道别。首先创建一个名为 `greetings` 的Cargo项目,并在 `src/main.rs` 文件中编写如下代码:
```rust
use std::io::stdin;
fn main() {
let name = get_name();
hello(&name);
goodbye(&name);
}
fn get_name() -> String {
let mut name = String::new();
println!("Please enter your name");
stdin().read_line(&mut name).unwrap();
name
}
fn goodbye(name: &str) {
println!("Goodbye, {}", name);
}
fn hello(name: &str) {
println!("Hello, {}", name);
}
```
运行这个程序,输入名字后,会得到相应的问候和道别信息。
为了更好地组织代码,我们可以将输入和输出功能分别放到不同的模块中。修改后的代码如下:
```rust
fn main() {
let name = get_name();
hello(&name);
goodbye(&name);
}
mod input {
use std::io::stdin;
fn get_name() -> String {
let mut name = String::new();
println!("Please enter your name");
std::io::stdin().read_line(&mut name).unwrap();
name
}
}
mod output {
fn goodbye(name: &str) {
println!("Goodbye, {}", name);
}
fn hello(name: &str) {
println!("Hello, {}", name);
}
}
```
然而,当我们尝试运行修改后的代码时,会遇到编译器错误,提示找不到 `get_name`、`hello` 和 `goodbye` 函数。这是因为这些函数被放在了 `input` 和 `output` 模块中,不再与 `main` 函数在同一个命名空间。解决方法是在 `main` 函数上方添加 `use` 语句来导入这些函数:
```rust
use input::get_name;
use output::{goodbye, hello};
fn main() {
let name = get_name();
hello(&name);
goodbye(&name);
}
mod input {
use std::io::stdin;
fn get_name() -> String {
let mut name = String::new();
println!("Please enter your name");
std::io::stdin().read_line(&mut name).unwrap();
name
}
}
mod output {
fn goodbye(name: &str) {
println!("Goodbye, {}", name);
}
fn hello(name: &str) {
println!("Hello, {}", name);
}
}
```
但此时又会出现新的错误,提示这些函数是私有的。在Rust中,所有函数默认是私有的,需要显式地标记为 `pub` 才能被外部访问。修改后的代码如下:
```rust
use input::get_name;
use output::{goodbye, hello};
fn main() {
let name = get_name();
hello(&name);
goodbye(&name);
}
mod input {
use std::io::stdin;
pub fn get_name() -> String {
let mut name = String::new();
println!("Please enter your name");
stdin().read_line(&mut name).unwrap();
name
}
}
mod output {
pub fn goodbye(name: &str) {
println!("Goodbye, {}", name);
}
pub fn hello(name: &str) {
println!("Hello, {}", name);
}
}
```
现在程序就可以正常运行了。使用模块的好处在于,它可以让我们更方便地组织代码,将相关的函数放在一起,便于维护和理解。
#### 3. 多文件模块
除了在同一个文件中定义模块,我们还可以将模块放在单独的文件中。目前,`input` 和 `output` 模块与其他代码在同一个 `main.rs` 文件中。如果模块比较大,通常建议将它们放在各自的文件中。具体做法是创建一个名为 `module.rs` 的新文件,将 `module` 替换为模块的名称。对于我们的示例,创建 `input.rs` 和 `output.rs` 文件。
`main.rs` 文件修改如下:
```rust
use input::get_name;
use output::{goodbye, hello};
mod input;
mod output;
fn main() {
let name = get_name();
hello(&name);
goodbye(&name);
}
```
`input.rs` 文件内容:
```rust
use std::io::stdin;
pub fn get_name() -> String {
let mut name = String::new();
println!("Please enter your name");
stdin().read_line(&mut name).unwrap();
name
}
```
`output.rs` 文件内容:
```rust
pub fn goodbye(name: &str) {
println!("Goodbye, {}", name);
}
pub fn hello(name: &str) {
p
```
0
0
复制全文
相关推荐









