Rust之包、单元包及模块

  • 包:一个用于构建、测试并分享单元包的Cargo功能;
  • 单元包:一个用于生成库或可执行文件的树形模块结构;
  • 模块及use关键字:被用于控制文件结构、作用域及路径的私有性;
  • 路径:一种用于命名条目的方法,这些条目包括结构体、函数和模块等。

1、包与单元包:

单元包可以被用于生成二进制程序或库。将Rust编译时所使用的入口文件称作这个单元包的根节点,它同时也是单元包的根模块。
包由一个或多个提供相关功能的单元包集合而成,它所附带的配置文件Cargo.toml描述了如何构建这些单元包的信息。
包包含的规则:

  • 一个包中只能拥有最多一个库单元包;
  • 包可以拥有任意多个二进制单元包;
  • 包内必须存在至少一个单元包(库单元包或二进制单元包)。

Cargo会默认将src/main.rs视作一个二进制单元包的根节点而无需指定,这个二进制单元包与包拥有相同的名称。当包中同时存在src/main.rssrc/lib.rs时,就会分别存在一个二进制单元包与一个库单元包,它们拥有与包相同的名称,可以在路径src/bin下添加源文件来创建出更多的二进制单元包,这个路径下的每个源文件都会被视作单独的二进制单元包。
单元包可以将相关的功能分组,并放到同一作用域下,这样便可以使这些功能轻松地在多个项目中共享。
将单元包的功能保留在它们自己的作用域中有助于指明某个特定功能来源于哪个单元包,并避免可能的命名冲突。

2、通过定义模块来控制作用域及私有性:

模块允许将单元包内的代码按照可读性与易用性来进行分组,同时还允许控制条目的私有性。即模块决定了一个条目是否可以被外部代码使用(公用),或者仅仅只是一个内部的实现细节而不对外暴露(私有)。
模块内可以继续定义其他模块,也同样可以包含其他条目的定义,例如:结构体、枚举、常量、trait等。
在Rust中src/main.rssrc/lib.rs被称为单元包的根节点,这两个文件的内容各自组成了一个名为crate的模块,并位于单元包模块结构的根部。这个模块结构也被称为模块树
模块树的结构:
在这里插入图片描述
当模块A被包含在模块B内时,将模块A称为模块B的子节点,模块B称为模块A的父节点。

3、用于在模块树中指明条目的路径:

为了在Rust的模块树中找到某个条目,同样需要使用路径。例如,在调用某个函数的时候,必须知道它的路径。
路径有两种形式:

  • 使用单元包名或字面量crate从根节点开始的绝对路径;
  • 使用self、super或内部标识符从当前模块开始的相对路径。

绝对路径与相对路径都由至少一个标识符组成,标识符之间使用双冒号::分隔。
Rust中的所有条目(函数、方法、结构体、枚举、模块及常量)默认都是私有的。处于父级模块中的条目无法使用子模块中的私有条目,但子模块中的条目可以使用它所有祖先模块中的条目。虽然子模块包装并隐藏了自身的实现细节,但它却依然能够感知当前定义环境中的上下文。

(1)、使用pub关键字来暴露路径:

为了能够让父模块中可以正常访问子模块中的函数,可以使用关键字pub来标记函数。示例:

mod front_of_house{
	pub mod hosting{
		pub add_to_waitlist(){}
	}
}
pub fn eat_at_restaurant() {
	 // 绝对路径
	 crate::front_of_house::hosting::add_to_waitlist();
	 // 相对路径
	 front_of_house::hosting::add_to_waitlist();
}

注意:仅将父模块设为pub,在访问时,子模块仍是私有的,对外不可见,需要将要调用的最终模块也设置为pub。一个模块的同级节点之间的访问不需要使用关键字pub

(2)、使用super关键字开始构造相对路径:

可以从父模块开始构造相对路径,这一方式需要在路径起始处使用super关键字。
示例:

fn serve_order(){}
mod back_of_house {
	fn fix_incorrect_order(){
		cook_order();
		super::serve_order();
	}
}

由于fix_incorrect_order函数处于back_of_house模块内,所以可以使用super关键字来跳转至back_of_house的父模块,也就是根模块处。从它开始,可以成功地找到 serve_order。

(3)、将结构体或枚举声明为公共的:

结构体和枚举都可以使用pub来声明为公共的,但是二者存在一定的差异。当在结构体前面使用pub时,结构体本身就成为了公共结构体,但是它的字段依旧保持了私有状态。可以逐一决定是否将某个字段公开。
示例:

mod back_of_house {
	pub struct Breakfast {
		pub toast: String,
		seasonal_fruit: String,
	}
	impl Breakfast {
		 pub fn summer(toast: &str) -> Breakfast {
			 Breakfast {
				 toast: String::from(toast),
				 seasonal_fruit: String::from("peaches"),
			 }
		 }
	 }
}

这里的toast是公共的,所以可以在别的函数中使用点号读写,但是seasonal_fruit字段是私有的,不可以直接使用点号进行读写。因为back_of_house::Breakfast拥有了一个私有字段,所以这个结构体需要提供一个公共的关联函数来构造Breakfast的实例(也就是本例中的summer)。如果缺少了这样的函数,将无法在别的函数中中创建任何的Breakfast实例。
与结构体不同的是,将一个枚举声明为公共的时,它所有的变体都自动变为了公共的,仅需要在enum关键字前放置pub。
示例:

mod back_of_house{
	pub enum Appetizer{
		Soup,
		Salad,
	}
}

这里的Soup和Salad都具有公共属性。

4、用use关键字将路径导入作用域:

借助关键字use可以将路径引入作用域,并像使用本地条目一样来调用路径中的目录。

mod front_of_house {
 pub mod hosting {
 pub fn add_to_waitlist() {}
 }
}
use crate::front_of_house::hosting;
pub fn eat_at_restaurant() {
 hosting::add_to_waitlist();
 hosting::add_to_waitlist();
 hosting::add_to_waitlist();
}

使用use来指定相对路径稍有一些不同。必须在传递给use的路径的开始处使用关键字self,而不是从当前作用域中可用的名称开始。

mod front_of_house {
 pub mod hosting {
 pub fn add_to_waitlist() {}
 }
}
use self::front_of_house::hosting;
pub fn eat_at_restaurant() {
 hosting::add_to_waitlist();
 hosting::add_to_waitlist();
 hosting::add_to_waitlist();
}

(1)、创建use路径时的惯用模式:

在使用关键字use指定函数路径时,只指定到函数的父模块,这意味着在调用函数时必须指定这个父模块,从而更清晰地表明当前函数有没有被定义在当前作用域,同样也能避免重复路径。

(2)、使用as关键字来提供新的名称:

使用use将同名类型引入作用域时所产生的问题还有另外一种解决办法:可以在路径后使用as关键字为类型指定一个新的本地名称,也就是别名。
示例:

use std::fmt::Result;
use std::io::Result as IoResult;
fn function1() -> Result {
 // --略
--
}
fn function2() -> IoResult<()> {
 // --略
--
}

(3)、使用pub usb重导出名称:

当我们使用use关键字将名称引入作用域时,这个名称会以私有的方式在新的作用域中生效。为了让外部代码能够访问到这些名称,可以通过组合使用pubuse实现。这项技术也被称作重导出。因为不仅将条目引入了作用域,而且使该条目可以被外部代码从新的作用域引入自己的作用域。

mod front_of_house {
	 pub mod hosting {
		 pub fn add_to_waitlist() {}
	 }
}
pub use crate::front_of_house::hosting;
pub fn eat_at_restaurant() {
	 hosting::add_to_waitlist();
	 hosting::add_to_waitlist();
	 hosting::add_to_waitlist();
}

(4)、使用嵌套的路径来清理众多use语句:

当想要使用同一个包或同一个模块内的多个条目时,将它们逐行列出会占据较多的纵向空间。可以在同一行内使用嵌套路径来将上述条目引入作用域。这一方法需要首先指定路径的相同部分,再在后面跟上两个冒号,接着用一对花括号包裹路径差异部分的列表。
示例:

use std::cmp::Ordering;
use std::io;
// ---略

可以写成:

use std::{cmp::Ordering, io};
// ---略

同理:

use std::io;
use std::io::Write;

可以写成:

use std::io::{self, Write};

(5)、通配符:

假如想要将所有定义在某个路径中的公共条目都导入作用域,那么可以在指定路径时在后面使用*通配符。
示例:

use std::collections::*;

上面这行use语句会将定义在std::collections内的所有公共条目都导入当前作用域。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/46719.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【电商小知识】7个步骤让你快速了解跨境电商!

近几年来&#xff0c;随着互联网的发展&#xff0c;国内外的商业贸易越来越流畅&#xff0c;直播电商的火爆也带动着一大批相关的产业链发展&#xff0c;其中跨境电商就是尤为突出的一个。尽管在国内做跨境电商的企业数量非常之多&#xff0c;但仍有许多新人争相入局&#xff0…

安防监控视频汇聚平台EasyCVR修改录像计划等待时间较长是什么原因?

安防监控视频EasyCVR视频融合汇聚平台基于云边端智能协同&#xff0c;支持海量视频的轻量化接入与汇聚、转码与处理、全网智能分发等。音视频流媒体视频平台EasyCVR拓展性强&#xff0c;视频能力丰富&#xff0c;具体可实现视频监控直播、视频轮播、视频录像、云存储、回放与检…

Ceph部署方法介绍

Ceph部署方法介绍 Installing Ceph — Ceph Documentation Ceph环境规划 admin是一个部署节点

计算机视觉:图像质量评价指标之 PSNR 和 SSIM

1. PSNR (Peak Signal-to-Noise Ratio) 峰值信噪比 由上可见&#xff0c;PSNR相对MSE多了一个峰值&#xff0c;MSE是绝对误差&#xff0c;再加上峰值是一个相对误差指标 一般地&#xff0c;针对 uint8 数据&#xff0c;最大像素值为 255,&#xff1b;针对浮点型数据&#xff…

低代码开发重要工具:jvs-flow(流程引擎)审批功能配置说明

流程引擎场景介绍 流程引擎基于一组节点与执行界面&#xff0c;通过人机交互的形式自动地执行和协调各个任务和活动。它可以实现任务的分配、协作、路由和跟踪。通过流程引擎&#xff0c;组织能够实现业务流程的优化、标准化和自动化&#xff0c;提高工作效率和质量。 在企业…

Python(Web时代)——初识flask

flask简介 介绍 Flask是一个用Python编写的Web 微框架&#xff0c;让我们可以使用Python语言快速实现一个网站或Web服务。它是BSD授权的&#xff0c;一个有少量限制的免费软件许可。它使用了 Werkzeug 工具箱和 Jinja2 模板引擎。 Flask 的设计理念是简单、灵活、易于扩展&a…

Java后端程序员不得不知道的 API 接口常识

说实话&#xff0c;我非常希望自己能早点看到本篇文章&#xff0c;大学那个时候懵懵懂懂&#xff0c;跟着网上的免费教程做了一个购物商城就屁颠屁颠往简历上写。 至今我仍清晰地记得&#xff0c;那个电商教程是怎么定义接口的&#xff1a; 管它是增加、修改、删除、带参查询&…

【Hammerstein模型的级联】快速估计构成一连串哈默斯坦模型的结构元素研究(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f308;4 Matlab代码实现 &#x1f4a5;1 概述 在许多振动应用中&#xff0c;所研究的系统略微非线性。Hammerstein模型的级联可以方便地描述这样的系统。Hammerstein提供了一种基于指数正弦…

关于在虚拟机CentOS7的Docker下安装Oracle

这不三阶段了&#xff0c;要上Oracle了&#xff0c;感觉这个班卷的程度到位。二阶段我就上了ElementUI和MyBatis&#xff0c;项目也是用这些技术写的&#xff0c;整体钻研程度还行。于是布置了两个任务&#xff1a;在windows下安一下Oracle&#xff0c;在windows下安装Oracle那…

需求管理全过程流程图及各阶段核心关注点详解

分析报告指出&#xff0c;多达76%的项目失败是因为差劲的需求管理&#xff0c;这个是项目失败的最主要原因&#xff0c;比落后的技术、进度失控或者混乱的变更管理还要关键。很多项目往往在开始的时候已经决定了失败&#xff0c;谜底就在谜面上&#xff0c;开始就注定的失败&am…

Redis缓存击穿问题以及解决方案

Redis缓存击穿问题以及解决方案 前言一、什么是Redis缓存击穿二、解决方案1.使用锁来解决使用锁的流程&#xff1a;核心思路&#xff1a;思路流程图&#xff1a;操作的锁的代码&#xff1a;业务的实现&#xff1a; 2.逻辑过期来解决思路分析&#xff1a;解决流程&#xff1a;业…

(一)RabbitMQ概念-优势、劣势、应用场景 、AMQP、工作原理

Lison <dreamlison163.com>, v1.0.0, 2023.06.22 RabbitMQ概念-优势、劣势、应用场景 、AMQP、工作原理 文章目录 RabbitMQ概念-优势、劣势、应用场景 、AMQP、工作原理RabbitMQ概念RabbitMQ的优势RabbitMQ劣势RabbitMQ应用的场景RabbitMQ_AMQPRabbitMQ工作原理 RabbitM…

NLP(六十二)HuggingFace中的Datasets使用

Datasets库是HuggingFace生态系统中一个重要的数据集库&#xff0c;可用于轻松地访问和共享数据集&#xff0c;这些数据集是关于音频、计算机视觉、以及自然语言处理等领域。Datasets 库可以通过一行来加载一个数据集&#xff0c;并且可以使用 Hugging Face 强大的数据处理方法…

Spring源码解析(五):循环依赖

Spring源码系列文章 Spring源码解析(一)&#xff1a;环境搭建 Spring源码解析(二)&#xff1a;bean容器的创建、默认后置处理器、扫描包路径bean Spring源码解析(三)&#xff1a;bean容器的刷新 Spring源码解析(四)&#xff1a;单例bean的创建流程 Spring源码解析(五)&…

企业电子招标采购系统源码之传统采购模式面临的挑战

采购类型多 采购制度&#xff1a;采购金额、部门、品类的差异导致管理标准不同。 采购流程&#xff1a;从供应商管理、寻源操作到合同签订、订单执行&#xff0c;业务流程长&#xff0c;审批节点多&#xff0c;传统管理透明度低&#xff0c;联动性差。 供应商管理难 寻源&#…

服务器VNC软件与服务器中Sentaurus TCAD软件相关问题汇总(持续更新中)

目录 license失效问题个人端口的VNC无法连接重启VNC后端口发生混乱/断电后个人端口无法连接操作的步骤在Centos环境下给Sentaurus TCAD安装编辑器jeditSSH重启VNC rootCentos查看NETMASK,GATWAY,DNS license失效问题 服务器terminal中输入如下命令&#xff1a;第一步&#xff…

教你使用PHP实现一个轻量级HTML模板引擎

&#x1f3c6;作者简介&#xff0c;黑夜开发者&#xff0c;全栈领域新星创作者✌&#xff0c;2023年6月csdn上海赛道top4。多年电商行业从业经验&#xff0c;对系统架构&#xff0c;数据分析处理等大规模应用场景有丰富经验。 &#x1f3c6;本文已收录于PHP专栏&#xff1a;PHP…

探索大型语言模型的开源人工智能基础设施:北京开源AI Meetup回顾

原文参见Explore open source AI Infra for Large Language Models: Highlights from the Open Source AI Meetup Beijing | Cloud Native Computing Foundation 背景介绍&#xff1a; 最近&#xff0c;在 ChatGPT 的成功推动下&#xff0c;大型语言模型及其应用程序的流行度激…

Mybatis学习笔记教程

Mybatis-9.28 环境&#xff1a; JDK1.8Mysql 5.7maven 3.6.1IDEA 回顾&#xff1a; JDBCMysqlJava基础MavenJunit SSM框架&#xff1a;配置文件的。 最好的方式&#xff1a;看官网文档&#xff1b; 1、简介 1.1、什么是Mybatis MyBatis 是一款优秀的持久层框架它支持定制…

opencv-25 图像几何变换04- 重映射-函数 cv2.remap()

什么是重映射&#xff1f; 重映射&#xff08;Remapping&#xff09;是图像处理中的一种操作&#xff0c;用于将图像中的像素从一个位置映射到另一个位置。重映射可以实现图像的平移、旋转、缩放和透视变换等效果。它是一种基于像素级的图像变换技术&#xff0c;可以通过定义映…