Rust: Rust 模块系统与 Cargo:代码组织与项目管理

最后更新:2026-08-26

模块系统是 Rust 的"代码寻址方案"——就像一栋楼的门牌号,让你能精确找到每一段代码的位置,并控制哪些代码可以被外部访问。

如果说一个大型项目是一座城市,那模块(mod)就是街区、文件就是建筑、函数就是房间。Cargo 则是城市管理局——负责修路、维护、检查质量。没有模块系统,代码就是堆在一起的"城中村"。


1. 你将学到


2. 公寓号牌系统的故事

(1) 痛苦:没有门牌号的城市

Tom 搬进了一栋新建的公寓楼,发现这里没有门牌号系统。

"如果有个统一的门牌号规则就好了:楼栋-单元-房间……"

(2) Rust 模块系统的方案

TEXT 📖 仅展示
公寓(Crate)           → 一栋楼
  楼栋名(crate name)   → 楼号
  单元(Module)         → 单元门
    房间号(Function)   → 具体的房间
RUST
// 文件结构对应关系:
// src/
//   main.rs              → 公寓大堂(入口)
//   building/
//     mod.rs             → 楼栋信息
//     unit_1/
//       mod.rs           → 1 单元
//       room_501.rs      → 501 室
//       room_502.rs      → 502 室

// 在 Rust 中,通过 mod 和 pub 精确控制谁可以访问什么
mod building {
    pub mod unit_1 {
        pub fn room_501() -> &'static str {
            "501 室:Tom 的家"
        }

        fn room_502() -> &'static str {
            "502 室:私密空间"  // 默认私有,外部不可见
        }
    }
}

fn main() {
    // 通过完整路径访问
    println!("{}", building::unit_1::room_501());
    // println!("{}", building::unit_1::room_502());  // ❌ 私有函数,编译错误
}

Rust 的模块系统就像公寓的门牌号系统:crate 是整栋楼,mod 是单元,fn 是房间。pub 控制哪些房间对外开门,没有 pub 的房间就是私密的——外人不能随便进。


3. 核心概念

(1) 模块系统与路径

100%
graph TB
    A[Rust 模块系统] --> B[mod 定义]
    A --> C[pub 可见性]
    A --> D[use 路径引入]
    A --> E[Cargo 项目管理]

    B --> B1["mod 模块名 { ... }"]
    B --> B2["mod 模块名;  // 从文件加载"]

    C --> C1["pub: 对外可见"]
    C --> C2["pub(crate): 仅 crate 内可见"]
    C --> C3["pub(super): 仅父模块可见"]
    C --> C4["无 pub: 私有的"]

    D --> D1["use crate::a::b::c;"]
    D --> D2["use super::module;"]
    D --> D3["use self::module;"]

    E --> E1["Cargo.toml 依赖"]
    E --> E2["cargo build / test"]
    E --> E3["workspace 多包"]
    E --> E4["lib.rs vs main.rs"]

(2) 可见性规则对比

可见性 关键字 谁可以访问 类比
私有 无(默认) 当前模块及子模块 只有自己家人能进卧室
父模块可见 pub(super) 父模块 楼上楼下邻居可以串门
Crate 内可见 pub(crate) 当前 crate 内所有模块 小区业主可以进小区大门
公开 pub 所有外部 crate 任何人都可以进商场

(3) 路径类型

路径类型 前缀 示例 说明
绝对路径 crate:: crate::utils::helper::foo 从 crate 根开始
相对路径 self:: self::helper::foo 从当前模块开始
相对路径 super:: super::helper::foo 从父模块开始
外部路径 包名 serde::Serialize 从外部 crate 开始

(4) Cargo 常用命令速查

命令 作用 常用选项
cargo new 创建新项目 --lib(库项目)
cargo build 编译项目 --release(优化编译)
cargo run 编译并运行 --bin name(指定二进制)
cargo check 快速检查编译错误 比 build 快,不生成二进制
cargo test 运行测试 test_name(指定测试)
cargo doc 生成文档 --open(自动打开浏览器)
cargo clippy 代码 lint 检查 -W clippy::all
cargo fmt 代码格式化 --check(仅检查不修改)
cargo add 添加依赖 --features xxx
cargo update 更新依赖锁文件 更新 Cargo.lock
cargo publish 发布到 crates.io 需先登录
cargo clean 清理编译产物 删除 target/ 目录

4. 模块与 Cargo 示例

▶ 示例 1:模块定义与 pub 可见性(难度 ⭐)

RUST
// ============================================
// 模块嵌套、pub 可见性、路径访问
// 演示:餐厅的厨房对顾客不可见,但对服务员可见
// ============================================

// 定义餐厅模块
mod restaurant {
    // 公开的:顾客可以进入餐厅
    pub struct Menu {
        pub name: String,
        price: f64,  // 默认私有,外部不可见
    }

    impl Menu {
        // 公开的构造函数
        pub fn new(name: &str, price: f64) -> Menu {
            Menu {
                name: name.to_string(),
                price,
            }
        }

        // 公开的方法:获取价格
        pub fn get_price(&self) -> f64 {
            self.price
        }
    }

    // 公开的:顾客可以点餐
    pub fn order_food(item: &str) -> String {
        // 私有的:厨房的操作对顾客不可见
        let prepared = prepare_in_kitchen(item);
        format!("您的 {} 已准备好: {}", item, prepared)
    }

    // 私有的:厨房是顾客不能进入的
    fn prepare_in_kitchen(item: &str) -> String {
        format!("[后厨] {} 正在烹饪中...", item)
    }

    // 嵌套模块:厨房内部
    mod kitchen {
        // 私有的存储区
        pub struct Storage {
            pub items: Vec<String>,
        }

        impl Storage {
            pub fn new() -> Storage {
                Storage {
                    items: vec![
                        "蔬菜".to_string(),
                        "肉类".to_string(),
                        "调料".to_string(),
                    ],
                }
            }
        }
    }
}

fn main() {
    // 访问公开的模块成员
    let dish = restaurant::order_food("宫保鸡丁");
    println!("{}", dish);

    // 创建公开的结构体
    let menu_item = restaurant::Menu::new("宫保鸡丁", 38.0);
    println!("菜品: {}, 价格: {:.1}元", menu_item.name, menu_item.get_price());

    // 以下代码无法编译(取消注释可试):
    // println!("厨师信息: {}", restaurant::prepare_in_kitchen("宫保鸡丁"));  // ❌ 私有函数
    // println!("价格: {}", menu_item.price);  // ❌ 私有字段
    // let storage = restaurant::kitchen::Storage::new();  // ❌ kitchen 模块是私有的
}

输出:

TEXT 📖 仅展示
您的 宫保鸡丁 已准备好: [后厨] 宫保鸡丁 正在烹饪中...
菜品: 宫保鸡丁, 价格: 38.0元

模块的可见性规则就像餐厅的物理布局:顾客(外部代码)只能进入餐厅大厅(pub 模块),不能进入厨房(私有模块)。厨房里的操作(prepare_in_kitchen)对外完全不可见——这就是封装(encapsulation)。


▶ 示例 2:use 路径与 super/crate(难度 ⭐⭐)

RUST
// ============================================
// use 关键字引入路径、super 与 crate 相对路径
// 模拟:公司组织架构——部门→小组→员工
// ============================================

// 顶层模块:公司
mod company {
    // 工程部门
    pub mod engineering {
        pub fn team_name() -> &'static str {
            "工程部"
        }

        // 前端小组
        pub mod frontend {
            pub fn member_count() -> u32 {
                5
            }

            // 使用 super 访问父模块(engineering)
            pub fn full_info() -> String {
                format!("{} 前端小组,{}人", super::team_name(), member_count())
            }
        }

        // 后端小组
        pub mod backend {
            pub fn member_count() -> u32 {
                8
            }

            // 使用 super 访问父模块
            pub fn full_info() -> String {
                format!("{} 后端小组,{}人", super::team_name(), member_count())
            }
        }
    }

    // 市场部门
    pub mod marketing {
        pub fn team_name() -> &'static str {
            "市场部"
        }

        // 使用 crate 路径从根访问
        pub fn total_employees() -> u32 {
            // 从 crate 根开始访问
            crate::company::engineering::frontend::member_count()
            + crate::company::engineering::backend::member_count()
            + self::member_count()
        }

        fn member_count() -> u32 {
            6
        }
    }
}

// 使用 use 引入路径——简化调用
use company::engineering::frontend;
use company::engineering::backend;
use company::marketing;

fn main() {
    // 方式 1:完整路径(不推荐,写起来太长)
    println!("{}", company::engineering::frontend::full_info());

    // 方式 2:use 引入后直接调用(推荐)
    println!("{}", frontend::full_info());
    println!("{}", backend::full_info());

    // 引入 marketing 模块
    println!("市场部人数: {}", marketing::member_count());

    // 使用 crate 路径访问
    println!("公司总人数: {}", marketing::total_employees());

    // 使用 as 别名避免冲突
    use company::engineering as eng;
    println!("部门: {}", eng::team_name());
}

输出:

TEXT 📖 仅展示
工程部 前端小组,5人
工程部 后端小组,8人
市场部人数: 6
公司总人数: 19
部门: 工程部

use 就像给"门牌号"设置快捷方式——不用每次都写完整的 company::engineering::frontend::full_info()super 是"往上走一层"(父模块),crate 是"回到大楼入口"(crate 根)。as 关键字可以给路径取别名,解决同名冲突。


▶ 示例 3:Cargo.toml 依赖管理与项目结构(难度 ⭐⭐)

RUST
// ============================================
// 模拟 Cargo 项目结构 + 依赖管理
// 演示:lib.rs 与 main.rs 的分工、外部依赖使用
// ============================================

// 注意:这个示例演示的是 lib.rs 中的代码
// 实际的 Cargo.toml 文件内容见下方注释

// ============================================
// Cargo.toml 内容(模拟):
// ============================================
// [package]
// name = "my-toolkit"
// version = "0.1.0"
// edition = "2021"
//
// [dependencies]
// serde = { version = "1.0", features = ["derive"] }
// serde_json = "1.0"
// chrono = "0.4"
// regex = "1.10"
//
// [dev-dependencies]
// rand = "0.8"
//
// [profile.release]
// opt-level = 3
// ============================================

// 工具模块:日期处理
pub mod date_utils {
    pub fn format_today() -> String {
        // 实际项目中会使用 chrono::Local::now()
        "2026-07-03".to_string()
    }

    pub fn is_weekend(day: &str) -> bool {
        day.ends_with("周六") || day.ends_with("周日")
    }
}

// 工具模块:字符串处理
pub mod string_utils {
    /// 验证邮箱格式(模拟正则匹配)
    pub fn validate_email(email: &str) -> bool {
        // 简化版验证:实际用 regex crate
        email.contains('@') && email.contains('.')
    }

    /// 去除非字母数字字符(模拟)
    pub fn sanitize(input: &str) -> String {
        input.chars()
            .filter(|c| c.is_alphanumeric() || *c == ' ')
            .collect()
    }
}

// 工具模块:数学计算
pub mod math_utils {
    /// 计算斐波那契数列第 n 项
    pub fn fibonacci(n: u32) -> u64 {
        match n {
            0 => 0,
            1 => 1,
            _ => fibonacci(n - 1) + fibonacci(n - 2),
        }
    }

    /// 判断是否为质数
    pub fn is_prime(n: u32) -> bool {
        if n < 2 {
            return false;
        }
        let limit = (n as f64).sqrt() as u32;
        for i in 2..=limit {
            if n % i == 0 {
                return false;
            }
        }
        true
    }
}

// 测试模块(使用 #[cfg(test)] 条件编译)
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_validate_email() {
        assert!(string_utils::validate_email("user@example.com"));
        assert!(!string_utils::validate_email("invalid"));
    }

    #[test]
    fn test_fibonacci() {
        assert_eq!(math_utils::fibonacci(0), 0);
        assert_eq!(math_utils::fibonacci(1), 1);
        assert_eq!(math_utils::fibonacci(10), 55);
    }

    #[test]
    fn test_is_prime() {
        assert!(math_utils::is_prime(17));
        assert!(!math_utils::is_prime(1));
        assert!(!math_utils::is_prime(4));
    }

    #[test]
    fn test_sanitize() {
        assert_eq!(string_utils::sanitize("hello@world!"), "hello world");
    }
}

// ============================================
// main.rs 中的代码(模拟):
// ============================================
// use my_toolkit::{
//     date_utils,
//     string_utils,
//     math_utils,
// };
//
// fn main() {
//     println!("今天日期: {}", date_utils::format_today());
//     println!("邮箱验证: {}", string_utils::validate_email("test@example.com"));
//     println!("质数检查: {}", math_utils::is_prime(17));
// }

fn main() {
    // 演示各工具函数
    println!("=== 工具库演示 ===");

    // 日期工具
    println!("今天: {}", date_utils::format_today());
    println!("是否是周末: {}", date_utils::is_weekend("周六"));

    // 字符串工具
    println!("邮箱验证 test@example.com: {}", string_utils::validate_email("test@example.com"));
    println!("邮箱验证 invalid: {}", string_utils::validate_email("invalid"));
    println!("净化 'hello@world!': {}", string_utils::sanitize("hello@world!"));

    // 数学工具
    println!("斐波那契第10项: {}", math_utils::fibonacci(10));
    println!("17 是质数吗: {}", math_utils::is_prime(17));
    println!("4 是质数吗: {}", math_utils::is_prime(4));

    println!("=== 演示结束 ===");

    // 运行测试的说明(实际项目中使用 cargo test)
    println!("使用 `cargo test` 运行单元测试");
}

输出:

TEXT 📖 仅展示
=== 工具库演示 ===
今天: 2026-07-03
是否是周末: true
邮箱验证 test@example.com: true
邮箱验证 invalid: false
净化 'hello@world!': hello world
斐波那契第10项: 55
17 是质数吗: true
4 是质数吗: false
=== 演示结束 ===
使用 `cargo test` 运行单元测试

真实项目的标准结构:lib.rs 放库代码(公共 API),main.rs 放可执行入口(使用 lib)。Cargo.toml 管理依赖,[dependencies] 是生产依赖,[dev-dependencies] 是测试/构建工具依赖。cargo test 自动发现并运行 #[test] 标记的函数。


▶ 示例 4:Cargo 常用命令与 workspace(难度 ⭐⭐⭐)

RUST
// ============================================
// Cargo 常用命令与 workspace 多包管理
// 模拟:一个 "任务管理器" workspace 项目
// ============================================

// ============================================
// 顶层 Cargo.toml(workspace):
// ============================================
// [workspace]
// members = [
//     "task-core",       // 核心库
//     "task-cli",        // CLI 工具
//     "task-web",        // Web 接口
// ]
//
// [workspace.package]
// version = "1.0.0"
// edition = "2021"
// ============================================

// ============================================
// task-core/Cargo.toml:
// ============================================
// [package]
// name = "task-core"
// version.workspace = true
// edition.workspace = true
//
// [dependencies]
// serde = { version = "1.0", features = ["derive"] }
// chrono = "0.4"
// ============================================

// 模拟 task-core 库的代码
pub mod task_core {
    use std::collections::HashMap;

    /// 任务优先级
    #[derive(Debug, Clone, PartialEq)]
    pub enum Priority {
        Low,
        Medium,
        High,
        Urgent,
    }

    /// 任务状态
    #[derive(Debug, Clone, PartialEq)]
    pub enum Status {
        Todo,
        InProgress,
        Done,
        Cancelled,
    }

    /// 核心任务结构体
    #[derive(Debug, Clone)]
    pub struct Task {
        pub id: u64,
        pub title: String,
        pub priority: Priority,
        pub status: Status,
        pub tags: Vec<String>,
    }

    impl Task {
        pub fn new(id: u64, title: &str, priority: Priority) -> Task {
            Task {
                id,
                title: title.to_string(),
                priority,
                status: Status::Todo,
                tags: Vec::new(),
            }
        }

        pub fn add_tag(&mut self, tag: &str) {
            self.tags.push(tag.to_string());
        }

        pub fn is_completed(&self) -> bool {
            self.status == Status::Done || self.status == Status::Cancelled
        }
    }

    /// 任务管理器
    pub struct TaskManager {
        tasks: HashMap<u64, Task>,
        next_id: u64,
    }

    impl TaskManager {
        pub fn new() -> TaskManager {
            TaskManager {
                tasks: HashMap::new(),
                next_id: 1,
            }
        }

        pub fn create_task(&mut self, title: &str, priority: Priority) -> u64 {
            let id = self.next_id;
            self.next_id += 1;
            let task = Task::new(id, title, priority);
            self.tasks.insert(id, task);
            id
        }

        pub fn get_task(&self, id: u64) -> Option<&Task> {
            self.tasks.get(&id)
        }

        pub fn complete_task(&mut self, id: u64) -> bool {
            if let Some(task) = self.tasks.get_mut(&id) {
                task.status = Status::Done;
                true
            } else {
                false
            }
        }

        pub fn list_tasks(&self) -> Vec<&Task> {
            let mut tasks: Vec<&Task> = self.tasks.values().collect();
            tasks.sort_by_key(|t| t.id);
            tasks
        }
    }
}

// ============================================
// Cargo 命令参考(注释中演示):
// ============================================
// 常用命令:
//   cargo new project_name      -- 创建新项目
//   cargo build                 -- 编译(debug)
//   cargo build --release       -- 编译(release 优化)
//   cargo run                   -- 编译 + 运行
//   cargo check                 -- 快速检查编译错误(不生成二进制)
//   cargo test                  -- 运行测试
//   cargo test test_name        -- 运行指定测试
//   cargo bench                 -- 运行性能基准测试
//   cargo doc --open            -- 生成文档并打开
//   cargo clippy                -- 代码 lint 检查
//   cargo fmt                   -- 代码格式化
//   cargo add crate_name        -- 添加依赖
//   cargo update                -- 更新依赖
//   cargo publish               -- 发布到 crates.io
//   cargo clean                 -- 清理编译产物
//
// Workspace 命令:
//   cargo build --workspace     -- 编译 workspace 中所有包
//   cargo test -p task-core     -- 只测试指定包
//   cargo run -p task-cli       -- 运行指定包

fn main() {
    use task_core::{Priority, TaskManager};

    println!("=== 任务管理器 (模拟 Workspace 项目) ===");

    let mut manager = TaskManager::new();

    // 创建任务
    let id1 = manager.create_task("学习 Rust 智能指针", Priority::High);
    let id2 = manager.create_task("完成模块系统练习", Priority::Medium);
    let id3 = manager.create_task("修复生产环境 Bug", Priority::Urgent);

    // 列出所有任务
    println!("\n--- 所有任务 ---");
    for task in manager.list_tasks() {
        println!("#{} [{:?}] {} - {:?}", task.id, task.priority, task.title, task.status);
    }

    // 完成一个任务
    manager.complete_task(id1);
    println!("\n完成 #{} 后:", id1);
    for task in manager.list_tasks() {
        let status = if task.is_completed() { "已完成" } else { "进行中" };
        println!("#{} {} - {}", task.id, task.title, status);
    }

    // 获取单个任务
    if let Some(task) = manager.get_task(id3) {
        println!("\n紧急任务: #{} {} ({:?})", task.id, task.title, task.priority);
    }

    println!("\n=== 演示结束 ===");
    println!("项目结构: task-core (库) + task-cli (CLI) + task-web (Web)");
    println!("使用 `cargo test -p task-core` 测试核心库");
    println!("使用 `cargo doc --open` 生成文档");
}

输出:

TEXT 📖 仅展示
=== 任务管理器 (模拟 Workspace 项目) ===

--- 所有任务 ---
#1 [High] 学习 Rust 智能指针 - Todo
#2 [Medium] 完成模块系统练习 - Todo
#3 [Urgent] 修复生产环境 Bug - Todo

完成 #1 后:
#1 学习 Rust 智能指针 - 已完成
#2 完成模块系统练习 - 进行中
#3 修复生产环境 Bug - 进行中

紧急任务: #3 修复生产环境 Bug (Urgent)

=== 演示结束 ===
项目结构: task-core (库) + task-cli (CLI) + task-web (Web)
使用 `cargo test -p task-core` 测试核心库
使用 `cargo doc --open` 生成文档

Workspace 是管理多包项目的利器:task-core 提供核心类型和逻辑(库),task-cli 提供命令行界面(可执行文件),task-web 提供 Web API(另一个可执行文件)。cargo build --workspace 一次性编译所有包。cargo test -p task-core 只测试核心库。


▶ 示例 5:综合练习——模块化设计模拟(难度 ⭐⭐⭐)

RUST
// ============================================
// 综合示例:模块可见性与 API 设计
// 模拟多文件项目结构(实际项目应拆分为独立文件)
// ============================================

mod math_utils {
    pub fn add(a: i32, b: i32) -> i32 { a + b }
    pub fn multiply(a: i32, b: i32) -> i32 { a * b }
    fn internal_check(val: i32) -> bool { val >= 0 }

    pub fn safe_divide(a: i32, b: i32) -> Option<i32> {
        if b == 0 { return None; }
        if !internal_check(a) || !internal_check(b) { return None; }
        Some(a / b)
    }

    pub mod constants {
        pub const PI: f64 = 3.14159265358979;
        pub const E: f64 = 2.71828182845905;
        pub const MAX_I32: i32 = i32::MAX;
    }
}

mod string_utils {
    pub fn capitalize(s: &str) -> String {
        let mut chars = s.chars();
        match chars.next() {
            None => String::new(),
            Some(first) => first.to_uppercase().collect::<String>() + chars.as_str(),
        }
    }

    pub fn truncate(s: &str, max_len: usize) -> String {
        if s.len() <= max_len { s.to_string() }
        else { format!("{}...", &s[..max_len.min(s.len())]) }
    }
}

mod user {
    pub struct User {
        pub name: String,
        age: u8,
        email: String,
    }

    impl User {
        pub fn new(name: &str, age: u8, email: &str) -> Self {
            User { name: name.to_string(), age, email: email.to_string() }
        }

        pub fn age(&self) -> u8 { self.age }

        pub fn summary(&self) -> String {
            format!("{} ({}岁, {})", self.name, self.age, self.email)
        }
    }
}

fn main() {
    use math_utils::{add, multiply, safe_divide, constants};
    use string_utils::{capitalize, truncate};
    use user::User;

    println!("=== math_utils 模块 ===");
    println!("2 + 3 = {}", add(2, 3));
    println!("4 * 5 = {}", multiply(4, 5));
    println!("10 / 3 = {:?}", safe_divide(10, 3));
    println!("10 / 0 = {:?}", safe_divide(10, 0));
    println!("PI = {:.5}, E = {:.5}", constants::PI, constants::E);

    println!("\n=== string_utils 模块 ===");
    println!("capitalize: '{}'", capitalize("rust"));
    println!("truncate: '{}'", truncate("Hello, World!", 8));

    println!("\n=== user 模块 ===");
    let alice = User::new("Alice", 30, "alice@example.com");
    println!("{}", alice.summary());
    println!("年龄: {}", alice.age());
}

输出:

TEXT 📖 仅展示
=== math_utils 模块 ===
2 + 3 = 5
4 * 5 = 20
10 / 3 = Some(3)
10 / 0 = None
PI = 3.14159, E = 2.71828

=== string_utils 模块 ===
capitalize: 'Rust'
truncate: 'Hello, ...'

=== user 模块 ===
Alice (30岁, alice@example.com)
年龄: 30

模块化设计三原则:pub 只暴露必要的 API(如 addsafe_divide),内部细节(如 internal_check)保持私有;子模块(如 constants)用 pub mod 暴露;结构体字段逐个标注可见性(pub name / age 私有 + age() getter)。


❓ 常见问题

Q modfn 有什么区别?为什么不用文件来组织?
A mod 是模块定义,fn 是函数定义。
Q pub(crate)pub 有什么区别?
A pub(crate) 只对同一 crate 内的代码可见,pub 对所有外部 crate 可见。
Q use super::xxxuse crate::xxx 什么时候用?
A super 用于访问父模块(相对路径),crate 用于从 crate 根开始访问(绝对路径)。
Q Cargo.toml 中的版本号 ^1.2.3 是什么意思?
A ^ 是"兼容性更新"——允许 >=1.2.3<2.0.0 的版本。
Q lib.rsmain.rs 可以同时存在吗?
A 可以。

📖 小节


📝 作业

  1. 难度 ⭐:创建一个包含两个模块 mathgreeting 的程序。math 模块有一个公开函数 add(a: i32, b: i32) -> i32greeting 模块有一个公开函数 say_hello(name: &str) -> String。在 main 中调用这两个函数。
  2. 难度 ⭐⭐:模拟一个"图书馆"模块系统。创建 library 模块,包含 books 子模块(图书管理)和 members 子模块(会员管理)。booksadd_booklist_books 函数,membersadd_memberlist_members 函数。使用 pub(super)pub(crate) 合理控制可见性。在 main 中演示添加图书和会员。
  3. 难度 ⭐⭐⭐:研究 Cargo workspace 项目结构。在本地创建一个 workspace 项目,包含 core-lib(库,提供 addsubtract 函数)和 cli-app(可执行文件,通过 core-lib 做计算并打印结果)。配置 Cargo.toml 的 workspace 设置,使用 cargo build --workspace 编译,cargo run -p cli-app 运行。
Web-Tutorial.com

Web-Tutorial 技术团队

由多位开发者共同维护的编程教程平台。每篇教程由对应领域的开发者编写和审核,确保内容准确可靠。如发现任何问题,欢迎向我们反馈。

100%

🙏 帮我们做得更好

我们是刚上线的编程教程站,几个人的小团队,精力有限。页面虽经检查,难免还有疏漏——链接失效、排版错乱、内容有误、语言生硬……

如果您发现了,麻烦告诉我们,我们会在收到反馈后第一时间进行修复,再次感谢您的光临 🙏