学习Rust的第11天:模块系统

news/2024/5/19 7:51:29

Rust的模块系统可以使用它来管理不断增长的项目,并跟踪 modules 存储在何处。

Rust的模块系统是将代码组织成逻辑片段的有效工具,因此可以实现代码维护和重用。模块支持分层组织、隐私管理和代码封装。Rust为开发人员提供了多功能和可扩展的方法来管理项目复杂性,其功能包括use关键字,嵌套路径以及将模块划分为独立文件的能力。

Introduction 介绍

In Rust, the module system helps keep code organized by grouping related functions, types, and other items together, making it easier to manage and reuse code in a project.
在Rust中,模块系统通过将相关的函数、类型和其他项分组在一起来帮助组织代码,从而更容易在项目中管理和重用代码。

For example: 举例来说:

Let’s say a part of your code is working with managing the database, you don’t really want it to be accessed by an image renderer. So we store them in different locations, in different modules
假设你的一部分代码是用来管理数据库的,你并不真的希望它被图像渲染器访问。所以我们把它们存放在不同的地方,不同的 modules

We can use the use keyword to access certain parts of a different modules.
我们可以使用 use 关键字来访问不同 modules 的某些部分。

When we run the cargo new command, we are technically creating a package and a package stores crates. There are two types of crates
当我们运行 cargo new 命令时,我们在技术上创建了一个包和一个包存储 crates 。有两种板条箱

  1. Binary crate : Can be executed directly
    Binary crate:可以直接执行
  2. Library crate : Can be used by other programs/packages
    Library crate:可以被其他程序/包使用

Each crate stores modules, That organize the code and control the privacy of your rust program.
每个箱子里都有模块,用来组织代码并控制生锈程序的隐私.

Let’s take a deeper look into it.
让我们深入了解一下。

Create a new package by running :
通过运行以下命令创建新包:

$ cargo new module_system
$ cd module_system
$ ls
Cargo.toml
src/

Reading the Cargo.toml file we can see :
阅读 Cargo.toml 文件,我们可以看到:

[package]
name = "module_system"
version = "0.1.0"
edition = "2021"[dependencies]

Due to the rust convention, We cannot really see any crates we have in this file but we do have a main.rs file. Which means that there is a binary crate named module_system in our package by default.
由于rust约定,我们在这个文件中看不到任何 crates ,但我们确实有一个 main.rs 文件。这意味着在我们的包中默认有一个名为 module_system 的二进制crate。

The same convention is followed for library crates, if lib.rs is present in out src directory, It will automatically create a library crate named module_system.
对于库crate也遵循相同的约定,如果 lib.rs 存在于 src 目录中,则会自动创建一个名为 module_system. 的库crate

Rules of packages and crates
包装和板条箱规则

  1. A package must have atleast one crate.
    一个包必须至少有一个板条箱。
  2. A package can either contain 0 library crates or 1 library crate
    一个包可以包含0个库箱或1个库箱
  3. A package can have n numbers of binary crates.
    一个包可以有 n 个二进制板条箱。

Modules 模块

Modules are library crates, defined with the mod keyword. They are used to structure a Rust application better, let’s take a look at an example to better understand it.
模块是用 mod 关键字定义的库箱。它们用于更好地构建Rust应用程序,让我们看一个例子来更好地理解它。

To create a library crate, we can use this command
要创建库crate,我们可以使用以下命令

cargo new --lib user
//File : src/lib.rsmod user{mod authentication{fn create_account(){}fn login(){}fn forgot_password(){}}mod edit_profile{fn change_username(){}fn chang_pfp(){}fn change_email(){}}
}

This is what a module would look like.
这就是模块的样子。

A module can have multiple modules inside of it, we can define, structs, enums, functions and more inside a module.
一个模块里面可以有多个模块,我们可以在一个模块里面定义,结构,枚举,函数等等。

This method helps a lot with managing and maintaining code-bases. In future if we had to change a certain something with the forgot_password function. We would know exactly where to find it…
这种方法对管理和维护代码库有很大帮助。在未来,如果我们不得不改变某些东西与 forgot_password 功能。我们就知道在哪能找到它...

Calling functions from a module
从模块调用函数

Let’s say, I want to enroll a new user into my service, and need to use the create_account function. How do I call it?
比如说,我想在我的服务中注册一个新用户,需要使用 create_account 函数。我该怎么称呼它?

//File : src/lib.rsmod user{pub mod authentication{pub fn create_account(){}fn login(){}fn forgot_password(){}}mod edit_profile{fn change_username(){}fn chang_pfp(){}fn change_email(){}}
}pub fn call_module_function(){//Absolute pathcrate::user::authentication::create_account();//Relative pathuser::authentication::create_account();
}

We added a pub keyword for out authentication module and create account function, because by default it is private and cannot be called, because of module privacy rules
我们为out authentication模块和create account函数添加了一个 pub 关键字,因为默认情况下它是 private ,由于模块隐私规则,它不能被调用

Relative path refers to accessing modules or items within the same module hierarchy without specifying the root, while absolute path refers to accessing them by specifying the root module or crate.
相对路径指的是在不指定根的情况下访问同一模块层次结构中的模块或项目,而绝对路径指的是通过指定根模块或crate来访问它们。

For reference, here is what the module hierarchy looks like…
作为参考,下面是模块层次结构的样子。

The super keyword can also be used for relatively calling a function, super allows us to reference the parent module…
关键字 super 也可以用于相对调用函数, super 允许我们引用父模块。

Example 例如

mod parent_module {pub fn parent_function() {println!("This is a function in the parent module.");}
}mod child_module {// Importing the `parent_function` from the parent module using `super`use super::parent_module;pub fn child_function() {println!("This is a function in the child module.");// Calling the parent function using `super`parent_module::parent_function();}
}fn main() {// Calling the child function which in turn calls the parent functionchild_module::child_function();
}

Module privacy rules 模块隐私规则

Modules have privacy rules that control which items (such as structs, functions, and variables) are visible or accessible from outside the module.
模块具有隐私规则,这些规则控制哪些项(如结构、函数和变量)可从模块外部看到或访问。

These rules help enforce encapsulation and prevent unintended access to internal details of a module.
这些规则有助于强制封装并防止意外访问模块的内部细节。

mod my_module {// Public structpub struct PublicStruct {pub public_field: u32,}// Private structstruct PrivateStruct {private_field: u32,}// Public function to create instances of `PrivateStruct`pub fn create_private_struct() -> PrivateStruct {PrivateStruct { private_field: 42 }}
}fn main() {// Creating an instance of PublicStruct is allowed from outside the modulelet public_instance = my_module::PublicStruct { public_field: 10 };println!("Public field of PublicStruct: {}", public_instance.public_field);// Creating an instance of PrivateStruct is not allowed from outside the module// let private_instance = my_module::PrivateStruct { private_field: 20 }; // This would give a compile-time error// Accessing the private field of PublicStruct is not allowed// println!("Private field of PublicStruct: {}", public_instance.private_field); // This would give a compile-time error// However, we can create and access instances of PrivateStruct using the provided public functionlet private_instance = my_module::create_private_struct();// println!("Private field of PrivateStruct: {}", private_instance.private_field); // This would give a compile-time error
}
  • Rust’s module system allows for organizing code into logical units.
    Rust的模块系统允许将代码组织成逻辑单元。
  • Visibility and access control in Rust modules are enforced through privacy rules.
    Rust模块中的可见性和访问控制通过隐私规则来实施。
  • In Rust, items (such as structs, functions, and variables) can be marked as either public or private within a module.
    在Rust中,项目(如结构、函数和变量)可以在模块中标记为public或private。
  • Public items are accessible from outside the module, while private items are not.
    公共项可以从模块外部访问,而私有项则不能。
  • Public items are typically designated with the pub keyword, while private items are not explicitly marked.
    公共项通常使用 pub 关键字指定,而私有项不显式标记。
  • Private items are only accessible within the module where they are defined, promoting encapsulation and hiding implementation details.
    私有项只能在定义它们的模块中访问,从而促进了封装并隐藏了实现细节。
  • The pub keyword is used to make items visible outside the module, allowing them to be used by other parts of the codebase.
    pub 关键字用于使项目在模块外部可见,允许代码库的其他部分使用它们。
  • The super keyword in Rust allows access to items in the parent module, facilitating hierarchical organization and access control within a crate.
    Rust中的 super 关键字允许访问父模块中的项目,促进了crate中的分层组织和访问控制。

Use Keyword 使用关键字

use keyword allows you to bring a path into scope, so that you dont have to specify a path over and over again, let’s take a look at our previous example.
use 关键字允许您将路径带入作用域,这样您就不必一遍又一遍地指定路径,让我们看看前面的示例。

//File : src/lib.rsmod user{pub mod authentication{pub fn create_account(){}fn login(){}fn forgot_password(){}}mod edit_profile{fn change_username(){}fn chang_pfp(){}fn change_email(){}}
}//adding the module to our scope
use crate::user::authentication;pub fn call_module_function(){//Instead of these, we can call it directly.//crate::user::authentication::create_account();//user::authentication::create_account();authentication::create_account();
}

Nested paths 嵌套路径

mod outer_module {pub mod inner_module {pub fn inner_function() {println!("This is an inner function.");}pub struct InnerStruct {pub value: i32,}}
}use outer_module::inner_module::inner_function;
use outer_module::inner_moduel::InnerStruct;fn main() {// Calling the inner functioninner_function();// Creating an instance of InnerStructlet inner_struct_instance = InnerStruct { value: 42 };println!("Value of inner struct: {}", inner_struct_instance.value);
}

Notice how both the use statements start with outer_module::inner_module::
请注意,两个 use 语句都以 outer_module::inner_module:: 开头

We can nest the two use statements by this:
我们可以这样嵌套两个 use 语句:

use outer_module::inner_module::{inner_function, InnerStruct};

Modules in separate files
单独文件中的模块

To keep better track of our project and structure it better, we can store different modules in separate files. Let’s do that to the authentication module.
为了更好地跟踪我们的项目并更好地构建它,我们可以将不同的模块存储在单独的文件中。让我们对 authentication 模块这样做。

mod user{pub mod authentication{pub fn create_account(){}fn login(){}fn forgot_password(){}}mod edit_profile{fn change_username(){}fn chang_pfp(){}fn change_email(){}}
}

Step 1 : Create a file in the src/ directory with the same name as the module, in out case authentication.rs
第1步:在 src/ 目录中创建一个与模块同名的文件,例如 authentication.rs

Step 2 : Copy all the functions to that file but keep the module declaration
步骤2:将所有函数复制到该文件,但保留模块声明

//File : src/authentication.rs
pub fn create_account(){}
fn login(){}
fn forgot_password(){}
//File : src/lib.rs
mod user{pub mod authentication; //change the curly brackets to a semicolonmod edit_profile{fn change_username(){}fn chang_pfp(){}fn change_email(){}}
}

What this does it, the compiler looks for the file with the same name as the module name and puts all the functions and other data in the module.We can also do this for parent modules as well…
这样做的目的是,编译器查找与模块名称同名的文件,并将所有函数和其他数据放入模块中。
我们也可以对父模块这样做.


http://www.mrgr.cn/p/30852560

相关文章

Docker in Docker的原理与实战

Docker in Docker(简称DinD)是一种在Docker容器内部运行另一个Docker实例的技术。这种技术允许用户在一个隔离的Docker容器中创建、管理和运行其他Docker容器,从而提供了更灵活和可控的部署选项。以下是DinD的主要特点: 隔离性&am…

element plus:tree拖动节点交换位置和改变层级

图层list里有各种组件,用element plus的tree来渲染,可以把图片等组件到面板里,面板是容器,非容器组件,比如图片、文本等,就不能让其他组件拖进来。 主要在于allow-drop属性的回调函数编写,要理清…

Linux2.6内核进程调度队列

目录 运行队列runqueue 活跃队列&过期队列 queue[140]&优先级&队列数组下标 bitmap[5]&O(1)调度算法 nr_active active指针和expired指针 O(1)调度算法之调度过程 本篇是Linux进程概念篇的最后一篇,Linux2.6内核是一个具体的/可行的/实际的存…

深入理解Linux文件系统和日志分析

目录 一.inode与block 1.inode与block概述 1.1.文件数据包括元信息与实际数据 1.2.文件存储在硬盘上,硬盘最小存储单位是“扇区”,每个扇区存储512字节 1.3.block(块) 1.4.inode(索引节点) 2.inode内…

军工单位安全内网文件导出,怎样做到严密的安全管控?

军工单位是指承担国家下达的军事装备、产品研制、生产计划任务的企、事业单位,主要包括电子工业部、航空工业总公司、航天工业总公司、兵器工业总公司、核工业总公司、船舶工业总公司、中国工程物理研究院及各省国防工业办公室等。 军工单位的特点主要体现在以下几个方面: 承…

Vue3中使用无缝滚动插件vue3-seamless-scroll

官网:https://www.npmjs.com/package/vue-seamless-scroll 1、实现效果文字描述: 表格中的列数据进行横向无缝滚动,某一列进行筛选的时候,重新请求后端的数据,进行刷新 2、安装:npm i vue3-seamless-scrol…

Keil和VSCode协同开发STM32程序

系列文章 STM32单片机系列专栏 C语言术语和结构总结专栏 文章目录 1. 配置环境 2. 测试打开工程 3. 测试编译工程 随着项目的复杂度上升,开发者不仅需要强大的硬件支持,还需要一个高效和灵活的开发环境。 vscode是一款集成大量可以便携开发插件的代码…

爬虫js逆向(python调用js学习)

首先介绍pyexecjs的使用 PyExecJs 是一个python 库,用于在 Python 环境中执行javaScript代码。它实际上是对 Execs 库的 Python 封装,Execls 本身是一个通用的 JavaScript 运行环境的抽象层。使用PyExecJs,你可以在Python 中执行JavaScript代码,而无需启动一个完整的JavaSc…

维基百科、百度百科和搜狗百科词条的创建流程

随着网络的发展,百度百科、搜狗百科、维基百科等百科网站已经成为大众获取知识的重要途径。因为百科具有得天独厚的平台优势,百科上的信息可信度高,权威性强。所以百科平台也成为商家的必争之地。这里小马识途聊聊如何创建百度百科、搜狗百科…

贪吃蛇(C语言版)

在我们学习完C语言 和单链表知识点后 我们开始写个贪吃蛇的代码 目标:使用C语言在Windows环境的控制台模拟实现经典小游戏贪吃蛇 贪吃蛇代码实现的基本功能: 地图的绘制 蛇、食物的创建 蛇的状态(正常 撞墙 撞到自己 正常退出&#xf…

智能组网怎么样?

智能组网技术的出现,使得网络连接更加便捷和智能化。无论我们身处何地,只要有网络覆盖,就能轻松进行远程连接和访问。智能组网到底如何实现的呢?本文将就智能组网的优势进行探讨,以便更好地了解其特点和应用场景。 【天…

idle的下载和环境配置(python)

1.进入官网:https://www.python.org/ 2.downloads->windows选择对应版本(这里我选择3.10.0是因为听说10比较稳定) 3. 找到刚下载的Python程序安装包,双击打开,运行安装程序。 直接点击下一步,直至安装成功,点击完成就可以了。如果想切换安装目录,可以在那一步换一下安…

自己手动在Linux上实现一个简易的端口扫描器

背景 常常听到网络攻击有一个东西叫做端口扫描器,可以扫描指定服务器开放的端口,然后尝试连接,并寻找漏洞,最终攻破服务器。而那些使用的端口扫描器都是一个个现成的程序,看上去很厉害的样子。而实际上这些东西对于懂…

[dp 小计] SOSdp

复健 SOSdp(sum over subsets dynamic programming)。 引入 令 \(F(x)=\sum\limits_{u\subseteq x} A(u)\) 其中 \(A\) 为给定数组,求出 \(\forall x, F(x)\) 。 思路一 暴力枚举子集,时间复杂度 \(O(4^n)\)。 思路二 优化子集枚举,时间复杂度 \(O(3^n)\)。 思路三 考虑 SOS…

HTTP慢连接攻击的原理和防范措施

随着互联网的快速发展,网络安全问题日益凸显,网络攻击事件频繁发生。其中,HTTP慢速攻击作为一种隐蔽且高效的攻击方式,近年来逐渐出现的越来越多。 为了防范这些网络攻击,我们需要先了解这些攻击情况,这样…

Redis篇:缓存击穿及解决方案

1.何为缓存击穿 缓存击穿问题也叫热点Key问题,就是一个被高并发访问并且缓存重建业务较复杂的key突然失效了(有可能是正好过期了),无数的请求访问会在瞬间给数据库带来巨大的冲击。 常见的解决方案有两种: 互斥锁 逻…

【深度学习】yolo-World,数据标注,zeroshot,目标检测

仓库:https://github.com/AILab-CVC/YOLO-World 下载权重: 仓库下载和环境设置 下载仓库:使用以下命令从 GitHub 上克隆仓库: git clone --recursive https://github.com/AILab-CVC/YOLO-World.git创建并激活环境&#xff1a…

Xinlinx FPGA内的存储器BRAM全解

目录 一、总体概述1.7系列FPGA的BRAM特点2.资源情况 二、BRAM分类1.单端口RAM2.简单双端口RAM3.真双端口RAM 三、BRAM的读写1、Primitives Output Registers读操作注意事项2.三种写数据模式(1)Write_First(2)Read_First&#xff0…

贪吃蛇的简单实现(c语言)

前言:学完了C语言的基础语法,和一点数据结构的知识,拿贪吃蛇来练练手,并熟悉以前的知识。写完之后,有一种成就感,为以后的学习饱满激情。 注意这里的讲解是由部分到整体的思路。 目录 控制台不能是终端&am…

UE4网络图片加载库(带内存缓存和磁盘缓存)

UE4网络图片加载库,带内存缓存和磁盘缓存,支持自定义缓存大小,支持蓝图和C++代码调用 1、调用示例 2、对外暴露函数 3、源代码-网络模块 KeImageNet.h // Fill out your copyright notice in the Description page of Project Settings.#pragma once#include "CoreM…