当前位置: 首页 > article >正文

深入理解 Rust 模块中的路径与公开性:绝对路径、相对路径和 `pub` 的应用

1. 路径的两种形式:绝对路径与相对路径

在 Rust 中,路径类似于文件系统中的目录路径,用来告诉编译器去哪里查找某个项。路径主要有两种形式:

  • 绝对路径
    绝对路径从 crate 的根开始。对于当前 crate 的代码,绝对路径以关键字 crate 开头;对于外部 crate,则以该 crate 的名称开始。
    示例:假设我们要调用 add_to_waitlist 函数,其完整的绝对路径可能是:

    crate::front_of_house::hosting::add_to_waitlist();
    
  • 相对路径
    相对路径则是从当前模块出发,利用 selfsuper 或直接用模块名称来指定路径。例如,如果当前模块与 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::SoupAppetizer::Salad,而无需单独标记每个变体为公共。

6. 小结与最佳实践

通过本文,我们了解了以下关键概念:

  • 路径的形式:绝对路径从 crate 或外部 crate 开始,而相对路径则以当前模块为起点,必要时可使用 selfsuper 等关键字。
  • 模块私有性:Rust 默认将所有项设为私有,使用 pub 可以有选择地暴露接口,从而形成稳定的公共 API。
  • 最佳实践
    • 在设计公共 API 时,将模块树组织在 src/lib.rs 中,确保只有明确标记为 pub 的项可供外部使用。
    • 在项目中使用绝对路径可以更好地分离代码定义和使用,减少因代码重构导致的路径修改。
    • 利用 super 构造相对路径,使得父子模块之间的引用更为灵活和稳健。

通过这些机制,Rust 为开发者提供了一套强大而灵活的模块系统,既能保持内部实现的封装,又能方便外部代码调用需要暴露的接口。

希望这篇博客能帮助你更深入地理解 Rust 模块中的路径引用与公开性设置,从而编写出更清晰、健壮的代码。Happy coding!

相关文章:

深入理解 Rust 模块中的路径与公开性:绝对路径、相对路径和 `pub` 的应用

1. 路径的两种形式:绝对路径与相对路径 在 Rust 中,路径类似于文件系统中的目录路径,用来告诉编译器去哪里查找某个项。路径主要有两种形式: 绝对路径 绝对路径从 crate 的根开始。对于当前 crate 的代码,绝对路径以关…...

基于钉钉API的连接器实现:企业数据集成与自动化管理

文章目录 概要背景与需求钉钉API概述连接器实现小结 概要 在当今数字化时代,企业面临着海量数据的管理与整合挑战。钉钉作为国内广泛使用的办公协作平台,提供了丰富的API接口,支持企业进行数据集成与自动化管理。本文将介绍如何通过钉钉API实…...

[Day 16]螺旋遍历二维数组

今天我们看一下力扣上的这个题目:146.螺旋遍历二维数组 题目描述: 给定一个二维数组 array,请返回「螺旋遍历」该数组的结果。 螺旋遍历:从左上角开始,按照 向右、向下、向左、向上 的顺序 依次 提取元素&#xff0c…...

【教程】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…...

【通俗易懂说模型】线性回归(附深度学习、机器学习发展史)

&#x1f308; 个人主页&#xff1a;十二月的猫-CSDN博客 &#x1f525; 系列专栏&#xff1a; &#x1f3c0;深度学习_十二月的猫的博客-CSDN博客 &#x1f4aa;&#x1f3fb; 十二月的寒冬阻挡不了春天的脚步&#xff0c;十二点的黑夜遮蔽不住黎明的曙光 目录 1. 前言 2. …...

【R语言】apply函数族

在R语言中使用循环操作时是使用自身来实现的&#xff0c;效率较低。所以R语言有一个符合其统计语言出身的特点&#xff1a;向量化。R语言中的向量化运用了底层的C语言&#xff0c;而C语言的效率比高层的R语言的效率高。 apply函数族主要是为了解决数据向量化运算的问题&#x…...

传统营销架构在当下如何进行优化转型?

随着市场环境的变化和数字技术的发展&#xff0c;传统营销架构越来越难以适应当下的营销市场。为了适应新时代的要求&#xff0c;企业也需要对营销架构进行优化转型。企业主可以着手从哪些方面进行调整呢&#xff1f;下面就来一同探讨下。 一、强调扁平化原则 扁平化与去中心化…...

QMK启用摇杆和鼠标按键功能

虽然选择了触摸屏&#xff0c;我仍选择为机械键盘嵌入摇杆模块&#xff0c;这本质上是对"操作连续性"的执着。   值得深思的是&#xff0c;本次开发过程中借助DeepSeek的代码生成与逻辑推理&#xff0c;其展现的能力已然颠覆传统编程范式&#xff0c;需求描述可自动…...

计算机网络-SSH基本原理

最近年底都在忙&#xff0c;然后这两天好点抽空更新一下。前面基本把常见的VPN都学习了一遍&#xff0c;后面的内容应该又继续深入一点。 一、SSH简介 SSH&#xff08;Secure Shell&#xff0c;安全外壳协议&#xff09;是一种用于在不安全网络上进行安全远程登录和实现其他安…...

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) &#xff1a;将xxx.pt模型转化成 xxx.onnx ONNX&#xff08;Ope…...

Linux在x86环境下制作ARM镜像包

在x86环境下制作ARM镜像包&#xff08;如qemu.docker&#xff09;&#xff0c;可以通过QEMU和Docker的结合来实现。以下是详细的步骤&#xff1a; 安装QEMU-user-static QEMU-user-static是一个静态编译的QEMU二进制文件&#xff0c;用于在非目标架构上运行目标架构的二进制文…...

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行业中&#xff0c;由于企业要降低成本、优化资源、分散风险以及满足市场需求和技术需求等原因&#xff0c;存在大量的外包岗位。很多人都说长…...

【B站保姆级视频教程:Jetson配置YOLOv11环境(七)Ultralytics YOLOv11配置】

Jetson配置YOLOv11环境&#xff08;7&#xff09;Ultralytics YOLOv11环境配置 文章目录 1. 下载YOLOv11 github项目2. 安装ultralytics包3. 验证ultralytics安装3.1 下载yolo11n.pt权重文件3.2 推理 1. 下载YOLOv11 github项目 创建一个目录&#xff0c;用于存放YOLOv11的项目…...

硬核技术:小程序能够调用手机的哪些传感器

一、加速度传感器 小程序可以调用手机的加速度传感器来检测设备的运动状态。加速度传感器能够测量设备在三个轴&#xff08;X、Y、Z&#xff09;上的加速度变化。通过分析这些数据&#xff0c;小程序可以实现一些功能&#xff0c;如运动检测、步数统计、游戏中的动作感应等。 健…...

Day 31 卡玛笔记

这是基于代码随想录的每日打卡 491. 非递减子序列 给你一个整数数组 nums &#xff0c;找出并返回所有该数组中不同的递增子序列&#xff0c;递增子序列中 至少有两个元素 。你可以按 任意顺序 返回答案。 数组中可能含有重复元素&#xff0c;如出现两个整数相等&#xff0…...

【蓝桥杯嵌入式】4_key:单击+长按+双击

全部代码网盘自取 链接&#xff1a;https://pan.baidu.com/s/1PX2NCQxnADxYBQx5CsOgPA?pwd3ii2 提取码&#xff1a;3ii2 1、电路图 将4个按键的引脚设置为input&#xff0c;并将初始状态设置为Pull-up&#xff08;上拉输入&#xff09; 为解决按键抖动的问题&#xff0c;我们…...

Synchronized和ReentrantLock面试详解

前言 接下来为大家带来的是 Java 中的两个典型锁代表&#xff1a;Synchronized 和 ReentrantLock 的详解 面试题&#xff1a;谈一谈AQS 在说 ReentrantLock 时&#xff0c;有必要先了解一下 AQS&#xff0c;因为 ReentrantLock 就是基于 AQS 实现的 分析&#xff1a; 共享…...

1.2 学习驱动(Driver)分为几步?

文章目录 前言一、什么是UVM中的驱动&#xff08;Driver&#xff09;&#xff1f;二、如何理解Driver&#xff1f;三、如何使用Driver&#xff1f;第一步&#xff1a;定义Driver类第二步&#xff1a;实现run_phase任务第三步&#xff1a;实现驱动任务第四步&#xff1a;实例化和…...

【MySQL篇】事务的认识以及四大特性

何为事务&#xff1f; 事务&#xff08;Transaction&#xff09;是指一组操作的集合&#xff0c;这些操作要么全部执行成功&#xff0c;要么全部不执行。事务通常用于保证数据库的一致性、完整性和可靠性&#xff0c;确保数据的完整性与正确性。 有效避免部分执行&#xff0c…...

2.7日学习总结

深入探究栈、队列与二叉树 一、栈的深度剖析 进阶特性&#xff1a;除了常规的入栈、出栈操作&#xff0c;栈在处理函数调用、表达式求值等场景时&#xff0c;展现出独特的递归模拟能力。利用栈可以将递归算法转化为非递归形式&#xff0c;有效避免因递归过深导致的栈溢出问题。…...