深入理解 Rust 模块中的路径与公开性:绝对路径、相对路径和 `pub` 的应用
1. 路径的两种形式:绝对路径与相对路径
在 Rust 中,路径类似于文件系统中的目录路径,用来告诉编译器去哪里查找某个项。路径主要有两种形式:
-
绝对路径
绝对路径从 crate 的根开始。对于当前 crate 的代码,绝对路径以关键字crate开头;对于外部 crate,则以该 crate 的名称开始。
示例:假设我们要调用add_to_waitlist函数,其完整的绝对路径可能是:crate::front_of_house::hosting::add_to_waitlist(); -
相对路径
相对路径则是从当前模块出发,利用self、super或直接用模块名称来指定路径。例如,如果当前模块与front_of_house同级,可以直接这样调用:front_of_house::hosting::add_to_waitlist();
选择使用哪种路径主要取决于代码重构时模块之间可能的移动。如果函数与其被调用项经常会一起移动,那么使用相对路径可能更方便;否则,绝对路径则提供了更稳定的引用。
2. 通过路径调用函数:一个示例
假设我们有如下模块结构(部分代码摘自 Listing 7-1):
crate└── front_of_house├── hosting│ └── add_to_waitlist└── serving├── take_order├── serve_order└── take_payment
我们希望在同一个 crate 根中定义一个名为 eat_at_restaurant 的函数来调用 add_to_waitlist 函数。可以使用两种不同的路径来实现这一目标:
- 使用绝对路径:
pub fn eat_at_restaurant() {// 从 crate 根开始,使用绝对路径调用 add_to_waitlistcrate::front_of_house::hosting::add_to_waitlist(); } - 使用相对路径:
pub fn eat_at_restaurant() {// 从当前模块开始,直接用模块名调用front_of_house::hosting::add_to_waitlist(); }
无论选择哪种方式,关键在于准确表达代码在模块树中的位置。
3. 模块私有性问题:编译错误的根源
在实际编译过程中,可能会遇到类似下面的错误:
error[E0603]: module `hosting` is private
这表明即使路径写得正确,由于 Rust 默认将模块中的所有项设置为私有,外部模块无法直接访问 hosting 模块中的内容。为了让父模块中的 eat_at_restaurant 能够调用 add_to_waitlist,不仅需要使 hosting 模块变为公共(使用 pub mod hosting;),还需要将 add_to_waitlist 函数本身声明为 pub。
例如,假设我们的代码如下:
// 在 src/lib.rs 中
mod front_of_house {// 将 hosting 模块标记为 pub,让外部可以访问该模块pub mod hosting {// add_to_waitlist 函数默认是私有的,需要加 pubpub fn add_to_waitlist() {println!("Adding to waitlist");}}
}pub fn eat_at_restaurant() {// 两种路径均可使用,因为模块与函数都已经公开crate::front_of_house::hosting::add_to_waitlist();// 或者:front_of_house::hosting::add_to_waitlist();
}
只有同时使用 pub 将模块和函数公开,调用代码才能通过编译。
4. 使用 super 构造相对路径
有时我们需要引用父模块中的项,此时可以使用 super 关键字,其效果类似于文件路径中的 ..。例如,在 back_of_house 模块中,假设有一个函数 fix_incorrect_order 需要调用父模块中的 deliver_order:
mod back_of_house {pub fn fix_incorrect_order() {// 使用 super 关键字引用父模块中的 deliver_ordersuper::deliver_order();}
}fn deliver_order() {println!("Order delivered!");
}
这种写法不仅直观,而且在模块重构时可以减少修改路径的地方,因为父子模块之间的相对关系保持不变。
5. 让 Struct 和 Enum 成为公共接口
除了函数和模块,结构体(structs)和枚举(enums)也是模块系统中常见的构建块。不过需要注意的是:
-
结构体(structs)
使用pub标记结构体可以使其整体公开,但结构体的字段默认仍然是私有的。如果希望外部代码能够访问或修改某些字段,需要在字段前也加上pub:pub struct Breakfast {pub toast: String, // 公开字段seasonal_fruit: String, // 私有字段 }impl Breakfast {// 提供公共关联函数来构造实例pub fn summer(toast: &str) -> Breakfast {Breakfast {toast: toast.to_string(),seasonal_fruit: String::from("peach"),}} }这样,外部代码可以访问
toast字段,但无法直接修改seasonal_fruit。 -
枚举(enums)
与结构体不同,枚举在声明为pub后,其所有变体默认都为公共的:pub enum Appetizer {Soup,Salad, }外部代码可以直接使用
Appetizer::Soup或Appetizer::Salad,而无需单独标记每个变体为公共。
6. 小结与最佳实践
通过本文,我们了解了以下关键概念:
- 路径的形式:绝对路径从
crate或外部 crate 开始,而相对路径则以当前模块为起点,必要时可使用self、super等关键字。 - 模块私有性:Rust 默认将所有项设为私有,使用
pub可以有选择地暴露接口,从而形成稳定的公共 API。 - 最佳实践:
- 在设计公共 API 时,将模块树组织在
src/lib.rs中,确保只有明确标记为pub的项可供外部使用。 - 在项目中使用绝对路径可以更好地分离代码定义和使用,减少因代码重构导致的路径修改。
- 利用
super构造相对路径,使得父子模块之间的引用更为灵活和稳健。
- 在设计公共 API 时,将模块树组织在
通过这些机制,Rust 为开发者提供了一套强大而灵活的模块系统,既能保持内部实现的封装,又能方便外部代码调用需要暴露的接口。
希望这篇博客能帮助你更深入地理解 Rust 模块中的路径引用与公开性设置,从而编写出更清晰、健壮的代码。Happy coding!
相关文章:
深入理解 Rust 模块中的路径与公开性:绝对路径、相对路径和 `pub` 的应用
1. 路径的两种形式:绝对路径与相对路径 在 Rust 中,路径类似于文件系统中的目录路径,用来告诉编译器去哪里查找某个项。路径主要有两种形式: 绝对路径 绝对路径从 crate 的根开始。对于当前 crate 的代码,绝对路径以关…...
基于钉钉API的连接器实现:企业数据集成与自动化管理
文章目录 概要背景与需求钉钉API概述连接器实现小结 概要 在当今数字化时代,企业面临着海量数据的管理与整合挑战。钉钉作为国内广泛使用的办公协作平台,提供了丰富的API接口,支持企业进行数据集成与自动化管理。本文将介绍如何通过钉钉API实…...
[Day 16]螺旋遍历二维数组
今天我们看一下力扣上的这个题目:146.螺旋遍历二维数组 题目描述: 给定一个二维数组 array,请返回「螺旋遍历」该数组的结果。 螺旋遍历:从左上角开始,按照 向右、向下、向左、向上 的顺序 依次 提取元素,…...
【教程】docker升级镜像
转载请注明出处:小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你,欢迎[点赞、收藏、关注]哦~ 目录 自动升级 手动升级 无论哪种方式,最重要的是一定要通过-v参数做数据的持久化! 自动升级 使用watchtower,可…...
使用jmeter进行压力测试
使用jmeter进行压力测试 jmeter安装 官网安装包下载,选择二进制文件,解压。 tar -xzvf apache-jmeter-x.tgz依赖jdk安装。 yum install java-1.8.0-openjdk环境变量配置,修改/etc/profile文件,添加以下内容。 export JMETER/…...
链表和 list
一、单链表的模拟实现 1.实现方式 链表的实现方式分为动态实现和静态实现两种。 动态实现是通过 new 申请结点,然后通过 delete 释放结点的形式构造链表。这种实现方式最能体 现链表的特性; 静态实现是利用两个数组配合来模拟链表。一个表示数据域&am…...
【AI大模型】Ubuntu18.04安装deepseek-r1模型+服务器部署+内网访问
以下内容主要参考博文:DeepSeek火爆全网,官网宕机?本地部署一个随便玩「LLM探索」 - 程序设计实验室 - 博客园 安装 ollama Download Ollama on Linux curl -fsSL https://ollama.com/install.sh | sh 配置 ollama 监听地址 ollama 安装后…...
cmd执行mysql命令
安装mysql之后如果想使用cmd执行mysql命令,需要怎么操作呢,下面一起看一下。 安装mysql之后,如果直接去cmd窗口执行MySQL命令,窗口可能会提示mysql不是可执行命令。 需要配置系统的环境变量,将mysql的安装路径配置系…...
网络安全威胁框架与入侵分析模型概述
引言 “网络安全攻防的本质是人与人之间的对抗,每一次入侵背后都有一个实体(个人或组织)”。这一经典观点概括了网络攻防的深层本质。无论是APT(高级持续性威胁)攻击、零日漏洞利用,还是简单的钓鱼攻击&am…...
【算法】动态规划专题⑦ —— 多重背包问题 + 二进制分解优化 python
目录 前置知识进入正题优化方法:二进制分解实战演练 前置知识 【算法】动态规划专题⑤ —— 0-1背包问题 滚动数组优化 python 【算法】动态规划专题⑥ —— 完全背包问题 python 进入正题 多重背包问题I https://www.acwing.com/problem/content/4/ 题目描述 有…...
详细教程 | 如何使用DolphinScheduler调度Flink实时任务
Apache DolphinScheduler 非常适用于实时数据处理场景,尤其是与 Apache Flink 的集成。DolphinScheduler 提供了丰富的功能,包括任务依赖管理、动态调度、实时监控和日志管理,能够有效简化 Flink 实时任务的管理和部署。通过 DolphinSchedule…...
PHP之hyperf学习笔记
Hyperf Model,Dao,Service,Contronller 路由 使用文件来配置路由,就是和laravel一样的 Router::addGroup(["middleware" > ["web", "auth"],"namespace" > "Hyperf\HttpServer\Contr…...
react的antd表格数据回显在form表单中
1、首先为table添加编辑按钮 {title: 操作,align: center,render: (_: any, record: any) > (<div style{{ display: flex, alignItems: center, justifyContent: space-evenly }}><Buttonsize"small"onClick{() > deitor(record)} style{{ margin…...
【通俗易懂说模型】线性回归(附深度学习、机器学习发展史)
🌈 个人主页:十二月的猫-CSDN博客 🔥 系列专栏: 🏀深度学习_十二月的猫的博客-CSDN博客 💪🏻 十二月的寒冬阻挡不了春天的脚步,十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前言 2. …...
【R语言】apply函数族
在R语言中使用循环操作时是使用自身来实现的,效率较低。所以R语言有一个符合其统计语言出身的特点:向量化。R语言中的向量化运用了底层的C语言,而C语言的效率比高层的R语言的效率高。 apply函数族主要是为了解决数据向量化运算的问题&#x…...
传统营销架构在当下如何进行优化转型?
随着市场环境的变化和数字技术的发展,传统营销架构越来越难以适应当下的营销市场。为了适应新时代的要求,企业也需要对营销架构进行优化转型。企业主可以着手从哪些方面进行调整呢?下面就来一同探讨下。 一、强调扁平化原则 扁平化与去中心化…...
QMK启用摇杆和鼠标按键功能
虽然选择了触摸屏,我仍选择为机械键盘嵌入摇杆模块,这本质上是对"操作连续性"的执着。 值得深思的是,本次开发过程中借助DeepSeek的代码生成与逻辑推理,其展现的能力已然颠覆传统编程范式,需求描述可自动…...
计算机网络-SSH基本原理
最近年底都在忙,然后这两天好点抽空更新一下。前面基本把常见的VPN都学习了一遍,后面的内容应该又继续深入一点。 一、SSH简介 SSH(Secure Shell,安全外壳协议)是一种用于在不安全网络上进行安全远程登录和实现其他安…...
yolov11模型在Android设备上运行【踩坑记录】
0) 参考资料: https://github.com/Tencent/ncnn?tabreadme-ov-file https://github.com/pnnx/pnnx https://github.com/nihui/ncnn-android-yolov5 https://github.com/Tencent/ncnn?tabreadme-ov-file 1) :将xxx.pt模型转化成 xxx.onnx ONNX(Ope…...
Linux在x86环境下制作ARM镜像包
在x86环境下制作ARM镜像包(如qemu.docker),可以通过QEMU和Docker的结合来实现。以下是详细的步骤: 安装QEMU-user-static QEMU-user-static是一个静态编译的QEMU二进制文件,用于在非目标架构上运行目标架构的二进制文…...
win编译openssl
一、perl执行脚本 1、安装perl脚本 perl安装 2、配置perl脚本 perl Configure VC-WIN32 no-asm no-shared --prefixE:\openssl-x.x.x\install二、编译openssl 1、使用vs工具编译nmake 如果使用命令行nmake编译会提示“无法打开包括文件: “limits.h”“ 等错误信息 所以…...
为什么说,在IT行业中长期从事外包岗位没有前途?
文章目录 前言一、职业发展与技能提升受限二、工作稳定性和归属感缺失三、薪资待遇和福利差异四、行业声誉和求职歧视总结 前言 在IT行业中,由于企业要降低成本、优化资源、分散风险以及满足市场需求和技术需求等原因,存在大量的外包岗位。很多人都说长…...
【B站保姆级视频教程:Jetson配置YOLOv11环境(七)Ultralytics YOLOv11配置】
Jetson配置YOLOv11环境(7)Ultralytics YOLOv11环境配置 文章目录 1. 下载YOLOv11 github项目2. 安装ultralytics包3. 验证ultralytics安装3.1 下载yolo11n.pt权重文件3.2 推理 1. 下载YOLOv11 github项目 创建一个目录,用于存放YOLOv11的项目…...
硬核技术:小程序能够调用手机的哪些传感器
一、加速度传感器 小程序可以调用手机的加速度传感器来检测设备的运动状态。加速度传感器能够测量设备在三个轴(X、Y、Z)上的加速度变化。通过分析这些数据,小程序可以实现一些功能,如运动检测、步数统计、游戏中的动作感应等。 健…...
Day 31 卡玛笔记
这是基于代码随想录的每日打卡 491. 非递减子序列 给你一个整数数组 nums ,找出并返回所有该数组中不同的递增子序列,递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。 数组中可能含有重复元素,如出现两个整数相等࿰…...
【蓝桥杯嵌入式】4_key:单击+长按+双击
全部代码网盘自取 链接:https://pan.baidu.com/s/1PX2NCQxnADxYBQx5CsOgPA?pwd3ii2 提取码:3ii2 1、电路图 将4个按键的引脚设置为input,并将初始状态设置为Pull-up(上拉输入) 为解决按键抖动的问题,我们…...
Synchronized和ReentrantLock面试详解
前言 接下来为大家带来的是 Java 中的两个典型锁代表:Synchronized 和 ReentrantLock 的详解 面试题:谈一谈AQS 在说 ReentrantLock 时,有必要先了解一下 AQS,因为 ReentrantLock 就是基于 AQS 实现的 分析: 共享…...
1.2 学习驱动(Driver)分为几步?
文章目录 前言一、什么是UVM中的驱动(Driver)?二、如何理解Driver?三、如何使用Driver?第一步:定义Driver类第二步:实现run_phase任务第三步:实现驱动任务第四步:实例化和…...
【MySQL篇】事务的认识以及四大特性
何为事务? 事务(Transaction)是指一组操作的集合,这些操作要么全部执行成功,要么全部不执行。事务通常用于保证数据库的一致性、完整性和可靠性,确保数据的完整性与正确性。 有效避免部分执行,…...
2.7日学习总结
深入探究栈、队列与二叉树 一、栈的深度剖析 进阶特性:除了常规的入栈、出栈操作,栈在处理函数调用、表达式求值等场景时,展现出独特的递归模拟能力。利用栈可以将递归算法转化为非递归形式,有效避免因递归过深导致的栈溢出问题。…...
