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

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.mzph.cn/news/827348.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

用 Pytorch 训练一个 Transformer模型

昨天说了一下Transformer架构,今天我们来看看怎么 Pytorch 训练一个Transormer模型,真实训练一个模型是个庞大工程,准备数据、准备硬件等等,我只是做一个简单的实现。因为只是做实验,本地用 CPU 也可以运行。 本文包含…

Vue阶段练习:tab栏、进度条、

阶段练习旨在学习完Vue 指令、计算属性、侦听器-CSDN博客后,进行自我检测,每个练习分为效果显示、需求分析、静态代码、完整代码、总结 四个部分,效果显示和准备代码已给出,我们需要完成“完整代码”部分。 练习1:tab栏…

开源大数据集群部署(二十一)Spark on yarn 部署

作者:櫰木 1 spark on yarn安装(每个节点) cd /root/bigdata/ tar -xzvf spark-3.3.1-bin-hadoop3.tgz -C /opt/ ln -s /opt/spark-3.3.1-bin-hadoop3 /opt/spark chown -R spark:spark /opt/spark-3.3.1-bin-hadoop32 配置环境变量及修改配…

攻防世界---misc---再见李华

1.下载附件是解压之后得到一张图片 2.使用常规方法后没有得到什么信息,接着用winhex分析,发现有压缩包 ,里面还有个key.txt 3.接着用kali使用命名foremost进行分离,得到压缩包,里面的key.txt需要密码 4.接着给压缩包暴…

IDEA代码重构

重构 重构的目的: 提高代码的可读性、可维护性、可扩展性和性能。 重命名元素 重命名类 当我们进行重命名操作的时候可以看到第六行存在一个R(rename),点击后就会弹出所偶有引用,这样可以避免我们在修改后存在遗漏引用处未修改。 我们可以通过…

管理集群工具之LVS

管理集群工具之LVS 集群概念 将很多机器组织在一起,作为一个整体对外提供服务集群在扩展性、性能方面都可以做到很灵活集群分类 负载均衡集群:Load Balance高可用集群:High Availability高性能计算:High Performance Computing …

模拟网关是什么?

模拟网关是一种网络设备,用于在模拟电话系统和数字网络之间进行信号转换。它的主要作用是将模拟语音信号转换为数字格式,使得这些信号能够通过基于IP(互联网协议)的网络进行传输,从而实现语音通信。这种设备是将传统的…

Python环境找不到解决方法

Python环境找不到 打开设置:Ctrl Alt S 添加Local Interpreter... 打开System Interpreter,找到本地安装的Python.exe路径,然后一路点OK Trust Project 如果打开工程时,出现如下对话框,请勾选 Trust projects in ...&…

项目管理中,项目团队如何高效的协作与沟通?

目 录 一、项目团队高效的协作与沟通,可以通过以下几个方面来实现: 二、如何在项目团队中明确和共享愿景以提高协作效率? 三、有效的沟通策略在项目管理中的应用案例有哪些? 四、建立哪些具体的沟通机制可以提升团队协作效率…

matlab学习003-绘制由差分方程表示的离散系统图像

目录 1,题目 2,使用函数求解差分方程 1)基础知识 ①filter函数和impz函数 ②zeros函数 ☀ 2)绘制图像 ​☀ 3)对应代码 如果连简单的信号都不会的,建议先看如下文章👇,之…

互联网大厂ssp面经,数据结构part2

1. 什么是堆和优先队列?它们的特点和应用场景是什么? a. 堆是一种特殊的树形数据结构,具有以下特点:i. 堆是一个完全二叉树,即除了最后一层外,其他层都是满的,并且最后一层的节点都靠左对齐。i…

SEGGER Embedded Studio IDE移植FreeRTOS

SEGGER Embedded Studio IDE移植FreeRTOS 一、简介二、技术路线2.1 获取FreeRTOS源码2.2 将必要的文件复制到工程中2.2.1 移植C文件2.2.2 移植portable文件2.2.3 移植头文件 2.3 创建FreeRTOSConfig.h并进行配置2.3.1 处理中断优先级2.3.2 configASSERT( x )的处理2.3.3 关于系…

linq select 和selectMany的区别

Select 和 SelectMany 都是 LINQ 查询方法&#xff0c;但它们之间有一些区别。 Select 方法用于从集合中选择特定的属性或对集合中的元素进行转换&#xff0c;并返回一个新的集合。例如&#xff1a; var numbers new List<int> { 1, 2, 3, 4, 5 }; var squaredNumbers…

SRS WebRTC Whip 和 Whep 部署体验问题

whip 報錯 404 webrtc推流 小窗口一闪而过&#xff0c;然后查看f12回复404的报错信息 chrome版本&#xff1a; 正在检查更新 版本 123.0.6312.123&#xff08;正式版本&#xff09; &#xff08;64 位&#xff09; centos 7.9 源码安装部署&#xff0c; 代码分支5.0 完全按…

socket通信基础讲解及示例-C

socket通信之C篇 服务端与客户端简介 socket通信服务端与客户端通信模型通信实战server&#xff08;服务端&#xff09;创建client&#xff08;客户端&#xff09;创建 函数详解创建套接字 socket绑定端口bind进入监听状态listen获取客户端连接请求accept接收网络数据read发送数…

每日一题---移除链表元素

文章目录 前言1.题目2.分析思路3.参考代码 前言 Leetcode–-移除链表元素 1.题目 2.分析思路 首先要创建一个新的链表&#xff0c;在定义三个指针&#xff0c;newHead&#xff0c;newTail和pcur&#xff0c;分别代表新链表头&#xff0c;新链表尾以及用于遍历原链表。 其次是…

Rust入门-所有权

一、为什么、是什么、怎么用 1、为什么Rust要提出一个所有权和借用的概念 所有的程序都必须和计算机内存打交道&#xff0c;如何从内存中申请空间来存放程序的运行内容&#xff0c;如何在不需要的时候释放这些空间&#xff0c;成为所有编程语言设计的难点之一。 主要分为三种…

git merge 和 git rebese的区别

git merge 和 git rebese的区别 拉取分支和合并代码会涉及两种选择&#xff0c;git merge 和 git rebase&#xff1a; rebase&#xff1a;变基&#xff0c;会有一个干净的分支&#xff0c;但是对于记录来源不够清楚merge&#xff1a;合并&#xff0c;git 分支看起来比较混乱&…

CentOS 7虚拟机配置静态IP地址(一)

IP地址的配置 以下几个地址需要记住&#xff0c;在配置中使用 &#xff08;1&#xff09;查看MAC地址&#xff08;点击菜单虚拟机-设置-网络适配器-高级-记住MAC地址&#xff09; &#xff08;2&#xff09;查看子网掩码和网关IP&#xff08;点击菜单编辑-虚拟网络编辑器-选择…

机器学习-10-神经网络python实现-从零开始

文章目录 总结参考本门课程的目标机器学习定义从零构建神经网络手写数据集MNIST介绍代码读取数据集MNIST神经网络实现测试手写的图片 带有反向查询的神经网络实现 总结 本系列是机器学习课程的系列课程&#xff0c;主要介绍基于python实现神经网络。 参考 BP神经网络及pytho…