包管理
约 1357 字大约 5 分钟
2025-09-26
提示
TODO 写的不好,有时间重新整理
Crate
crate 是 Rust 在编译时最小的代码单位,crate 有两种形式
- 二进制
crate可以被编译为可执行程序,它们必须有一个main函数来作为执行入口 - 库 crate 没有
main函数,也不会被编译为可执行程序,但它们定义了可供多个项目复用的功能模块
包
包是提供系列功能的一个或多个 crate 的捆绑。一个包会包含一个 Cargo.toml 文件,阐述如何去构建这些 crate
注
Cargo实际上就是一个包,它包含了用于构建代码的命令行工具的二进制crate- 包中可以包含至多一个库
crate或任意多个二进制crate,但必须至少有一个
模块
可以在一个 crate 中通过 模块 来进行代码分组,以提高可读性与复用性。定义一个模块使用关键字 mod,后跟模块名
在一个模块中的代码 默认是私有的 因此使用模块还可以控制 项(私有项)的 私有性。如果项让模块及其内部的项是公共的,则需要使用 pub 关键字来修饰
模块树
Rust crate 分为二进制和库两种形式,分别以 src/main.rs 与 src/lib.rs 作为 crate 根。根文件的内容形成名为 crate 的顶层模块,自此向下的嵌套就是整棵 "模块树"。
mod front_of_house {
mod hosting {
fn add_to_waitlist() {}
fn seat_at_table() {}
}
mod serving {
fn take_order() {}
fn serve_order() {}
fn take_payment() {}
}
}重要
pub只影响可见性,不改变所有权;嵌套模块默认私有,需要逐层pub才能被外部访问- 结构体中,如果只给结构体名称设置为
pub那么这个结构体会变为公有的,但其内部字段仍是私有的,此时可根据情况决定其内部字段是否公有 - 枚举中,若枚举本身是
pub enum,则默认其变体对外可见
除了私有性,通过 pub 关键字还可以控制项的可见性
pub(crate)仅本 crate 内可见pub(super)仅父模块可见pub(in path)限定到指定模块路径,用于在内部共享但不暴露给依赖方
模块引用
使用一个模块中的某一项时,通常需要通过模块路径来引用。模块路径由模块名组成,模块名由 :: 分隔。路径有两种形式
- 相对路径: 从当前模块开始,以
self、super或当前模块中的某个标识符开头 - 绝对路径: 以
crate开头的完整路径
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}
pub fn eat_at_restaurant() {
// 绝对路径
crate::front_of_house::hosting::add_to_waitlist();
// 相对路径
front_of_house::hosting::add_to_waitlist();
}fn deliver_order() {}
mod back_of_house {
fn fix_incorrect_order() {
cook_order();
super::deliver_order();
}
fn cook_order() {}
}use
use 关键字用于在前作用域为路径创建一个 "别名/快捷方式" 避免反复写长路径。它不改变可见性,只是把某个已可见的项导入到当前作用域后,可以直接用简短名字调用
use crate::garden::vegetables::Asparagus;
fn main() {
let a = Asparagus {};
}注
- 导入函数时,习惯于
use到父模块,调用时写父模块::函数名,既减少重复又能看出函数不在当前模块定义 - 导入类型(结构体/枚举等)时,习惯
use到具体类型,直接使用类型名 - 如需同时导入同名项,保留到父模块以区分
as 别名
使用 as 别名,也可以解决 use 将两个同名类型引入同一作用域的问题
use std::fmt::Result;
use std::io::Result as IoResult;
fn function1() -> Result {
}
fn function2() -> IoResult<()> {
}pub use 重新导出
当使用 use 将某个模块导入进当前作用域后,该模块对当前作用域之外的作用域依然是私有的,若想要让当前作用域以外的作用域依然能够访问这个模块,就可以使用 pub use 的方式,来将导入的模块重新暴露出去
mod front_of_house {
pub mod hosting {
pub fn add_to_waitlist() {}
}
}mod front_of_house;
// 重新暴露
pub use front_of_house::hosting;
pub fn eat_at_restaurant() {}嵌套路径
从同一个模块中导入大量的内容时,为每一项的引入单独列出一行会占用源码大量的垂直空间,因此就可以使用嵌套路径将来自相同模块中的项在一行中引入作用域,从而减少源码的垂直空间占用
使用方式就是通过 ::{} 将来自相同模块下的项放入一个 use 语句
use std::{cmp::Ordering, io};当多个路径共享同一前缀,且其中一个就是前缀本身,可用 self 表示当前前缀,避免重复书写
use std::io::{self, Write};全部导出
如果想将一个路径下的所有公共项引入作用域,可以直接在路径后跟 * 来实现
use std::collections::*;注
通配导入(*)容易引入命名冲突且不易追踪来源,通常仅在少量场景(测试、prelude)中使用