ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

用 rustlings 系统掌握 Rust 模块系统:pub 可见性、use 路径导入与 pub use 重导出

用 rustlings 系统掌握 Rust 模块系统:pub 可见性、use 路径导入与 pub use 重导出 用 rustlings 系统掌握 Rust 模块系统pub 可见性、use 路径导入与 pub use 重导出【免费下载链接】rustlings:crab: Small exercises to get you used to reading and writing Rust code!项目地址: https://gitcode.com/gh_mirrors/ru/rustlings本篇围绕 rustlings 仓库中exercises/10_modules/模块章节对应官方文档 exercises/10_modules/README.md展开介绍 Rust 模块系统module system的三个核心能力默认私有与pub可见性控制、use/as将模块路径引入作用域并重命名、以及通过pub use向外部暴露与内部结构不同的接口。你将跟随 modules1~modules3 三道练习题的完整代码掌握如何在真实工程中组织代码可见性与命名空间。模块章节定位与练习构成exercises/10_modules/README.md是 rustlings 课程中模块章节的导读其核心目标是给出 Rust 模块系统的入门指引。在 rustlings 的练习体系中该章节由三道源码文件组成各自聚焦一个知识点练习文件考察重点官方提示hintmodules1.rsmod与可见性模块内函数默认私有需用pub对外暴露Everything is private in Rust by default. But theres a keyword we can use to make something public!Rust 中一切默认私有但有一个关键字可以把它变为公开modules2.rsuse ... as重命名 pub use重导出提示要补齐两条use语句并找到两个常量都缺少的一个关键字modules3.rs用嵌套路径一行引入标准库模块提示UNIX_EPOCH与SystemTime声明在std::time模块中可用嵌套路径一行引入三道练习的 hint 文本集中维护在 rustlings-macros/info.toml 的[[exercises]]配置段中其中modules1~modules3均标记为test false意味着 rustlings 只要求练习编译通过modules3额外要求运行时不 panic而不依赖单元测试断言。modules1模块边界与 pub 可见性练习代码与报错modules1.rs 构造了一个典型的模块内部实现场景——香肠工厂sausage_factory模块// TODO: Fix the compiler error about calling a private function. mod sausage_factory { // Dont let anybody outside of this module see this! fn get_secret_recipe() - String { String::from(Ginger) } fn make_sausage() { get_secret_recipe(); println!(sausage!); } } fn main() { sausage_factory::make_sausage(); }这段代码无法通过编译main中调用sausage_factory::make_sausage()时make_sausage没有pub修饰属于私有项模块外部main所在的根作用域不可访问。这正是 Rust 的可见性规则——一切默认私有且可见性按模块边界逐层生效只有当前模块及其子模块能看到当前模块中的私有项。修复方式与官方解法对照 solutions/10_modules/modules1.rs官方解法只改了一处mod sausage_factory { fn get_secret_recipe() - String { String::from(Ginger) } // Added pub before fn to make the function accessible outside the module. pub fn make_sausage() { get_secret_recipe(); println!(sausage!); } } fn main() { sausage_factory::make_sausage(); }get_secret_recipe保持私有make_sausage加上pub。这个细节值得注意修复的最小改动是只暴露必要的 APImake_sausage而不必把秘方函数也公开。这体现了 Rust 模块设计的一个惯用做法——用模块边界封装内部实现对外仅暴露最小公开面调用方只能经由make_sausage间接触达get_secret_recipe。modules2use/as 引入路径与 pub use 重导出练习代码modules2.rs 要求模块对外呈现一套与内部结构不同的接口。内部结构是两个子模块fruits和veggies各自定义公开常量mod delicious_snacks { // TODO: Add the following two use statements after fixing them. // use self::fruits::PEAR as ???; // use self::veggies::CUCUMBER as ???; mod fruits { pub const PEAR: str Pear; pub const APPLE: str Apple; } mod veggies { pub const CUCUMBER: str Cucumber; pub const CARROT: str Carrot; } } fn main() { println!( favorite snacks: {} and {}, delicious_snacks::fruit, delicious_snacks::veggie, ); }注意main中期望的路径是delicious_snacks::fruit和delicious_snacks::veggie——小写、无子模块前缀与内部fruits::PEAR、veggies::CUCUMBER的结构完全不同。因此需要两件事用use ... as把常量路径引入delicious_snacks作用域并重命名让外部能沿delicious_snacks::fruit这个路径找到它们——即use本身还要公开。修复方式pub use 重导出对照 solutions/10_modules/modules2.rsmod delicious_snacks { // Added pub and used the expected alias after as. pub use self::fruits::PEAR as fruit; pub use self::veggies::CUCUMBER as veggie; mod fruits { pub const PEAR: str Pear; pub const APPLE: str Apple; } mod veggies { pub const CUCUMBER: str Cucumber; pub const CARROT: str Carrot; } }几个要点self::前缀在模块内部以self指代当前模块本身self::fruits::PEAR即本模块下 fruits 子模块的 PEAR。as重命名use self::fruits::PEAR as fruit;创建别名fruit使main中delicious_snacks::fruit的写法成立。pub use重导出这是官方 hint 中所说的两个常量都缺少的一个关键字。若只写use不加pub别名仅在当前模块内部可见main依然无法访问加上pub后delicious_snacks模块就对外重导出了fruit/veggie两个名字而内部真实结构fruits、veggies子模块及常量仍然保持私有。这正是模块作为接口边界的体现——外部使用者只看到delicious_snacks::fruit看不到其内部组织。modules3一行引入标准库模块嵌套路径modules3.rs 的场景是计算当前时间距 UNIX 纪元的秒数代码中直接使用了SystemTime与UNIX_EPOCH但尚未引入作用域// TODO: Bring SystemTime and UNIX_EPOCH from the std::time module into // your scope. Bonus style points if you can do it with one line! // use ???; fn main() { match SystemTime::now().duration_since(UNIX_EPOCH) { Ok(n) println!(1970-01-01 00:00:00 UTC was {} seconds ago!, n.as_secs()), Err(_) panic!(SystemTime before UNIX EPOCH!), } }官方解法 solutions/10_modules/modules3.rs 用一条嵌套路径语句同时引入两个名字拿到题目所说的Bonus style pointsuse std::time::{SystemTime, UNIX_EPOCH};这里use的路径不限于自己项目的模块树同样适用于标准库std::time。大括号语法use 路径::{A, B};允许在一条语句中导入同一模块下的多个项比写两行use std::time::SystemTime; use std::time::UNIX_EPOCH;更简洁。test false的校验方式下该练习的通过标准是编译通过且运行main正常打印若时钟早于 UNIX 纪元会触发 panic正常系统下不会。rustlings 如何组织与校验这些练习从仓库结构看模块章节的练习文件、解法文件与校验配置是分离维护的练习源码位于 exercises/10_modules/配套解法位于 solutions/10_modules/一一对应dev/Cargo.toml 将每个练习注册为 workspace 成员并同时引入练习版与解法版两个 target例如{ name modules1, path ../exercises/10_modules/modules1.rs }, { name modules1_sol, path ../solutions/10_modules/modules1.rs }, { name modules2, path ../exercises/10_modules/modules2.rs }, { name modules2_sol, path ../solutions/10_modules/modules2.rs }, { name modules3, path ../exercises/10_modules/modules3.rs }, { name modules3_sol, path ../solutions/10_modules/modules3.rs },这说明 rustlings 的校验流程是把每个.rs练习作为独立编译单元进行编译_sol版本则用于验证解法可编译通过每个练习的元数据目录、是否含测试、hint 文本记录在 rustlings-macros/info.toml 中模块三道题均为test false即纯编译校验与 tests/test_exercises/info.toml 中带测试用例如test_failure的练习形成对照练习文件顶部的// TODO:注释即为需要修改的位置官方 hint 会给出方向而不直接给答案如 modules1 的 hint 只提示有一个关键字可以让项变公开。学习者通常通过cargo runrustlings CLI或cargo dev驱动开发循环来完成本章节阅读报错 → 按 hint 方向修改 → 编译/运行通过即过关。小结模块三要素速查语法作用本章节出处mod name { ... }声明模块划定作用域边界内部项默认私有modules1.rspub使项函数/常量/模块对模块外部可见modules1 解法、modules2 解法use 路径 as 别名;引入模块路径并在新作用域重命名modules2 解法pub use ...;重导出名字对外暴露与内部结构不同的接口modules2 解法use a::b::{X, Y};嵌套路径一行引入多个标准库项modules3 解法完成本章后建议继续回顾 Rust 官方书籍 The Book 第 7 章Managing Growing Projects with Packages, Crates, and Modules中用 use 关键字把路径引入作用域一节的pub use重导出小节以补全本章练习涉及的完整知识背景。【免费下载链接】rustlings:crab: Small exercises to get you used to reading and writing Rust code!项目地址: https://gitcode.com/gh_mirrors/ru/rustlings创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表