Rust组织管理,箱Crate包Package和模块module定义和区别,use关键字作用

本文主要是介绍Rust组织管理,箱Crate包Package和模块module定义和区别,use关键字作用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Rust 组织管理

任何一门编程语言如果不能组织代码都是难以深入的,几乎没有一个软件产品是由一个源文件编译而成的。

本教程到目前为止所有的程序都是在一个文件中编写的,主要是为了方便学习 Rust 语言的语法和概念。

对于一个工程来讲,组织代码是十分重要的。

Rust 中有三个重要的组织概念:箱、包、模块。

箱(Crate)

"箱"是二进制程序文件或者库文件,存在于"包"中。

"箱"是树状结构的,它的树根是编译器开始运行时编译的源文件所编译的程序。

注意:"二进制程序文件"不一定是"二进制可执行文件",只能确定是是包含目标机器语言的文件,文件格式随编译环境的不同而不同。

包(Package)

当我们使用 Cargo 执行 new 命令创建 Rust 工程时,工程目录下会建立一个 Cargo.toml 文件。工程的实质就是一个包,包必须由一个 Cargo.toml 文件来管理,该文件描述了包的基本信息以及依赖项。

一个包最多包含一个库"箱",可以包含任意数量的二进制"箱",但是至少包含一个"箱"(不管是库还是二进制"箱")。

当使用 cargo new 命令创建完包之后,src 目录下会生成一个 main.rs 源文件,Cargo 默认这个文件为二进制箱的根,编译之后的二进制箱将与包名相同。

模块(Module)

对于一个软件工程来说,我们往往按照所使用的编程语言的组织规范来进行组织,组织模块的主要结构往往是树。Java 组织功能模块的主要单位是类,而 JavaScript 组织模块的主要方式是 function。

这些先进的语言的组织单位可以层层包含,就像文件系统的目录结构一样。Rust 中的组织单位是模块(Module)。

mod nation {mod government {fn govern() {}}mod congress {fn legislate() {}}mod court {fn judicial() {}}
}

这是一段描述法治国家的程序:国家(nation)包括政府(government)、议会(congress)和法院(court),分别有行政、立法和司法的功能。我们可以把它转换成树状结构:

nation├── government│ └── govern├── congress│ └── legislate└── court└── judicial

在文件系统中,目录结构往往以斜杠在路径字符串中表示对象的位置,Rust 中的路径分隔符是 :: 。

路径分为绝对路径和相对路径。绝对路径从 crate 关键字开始描述。相对路径从 self 或 super 关键字或一个标识符开始描述。例如:

crate::nation::government::govern();

是描述 govern 函数的绝对路径,相对路径可以表示为:

nation::government::govern();

现在你可以尝试在一个源程序里定义类似的模块结构并在主函数中使用路径。

如果你这样做,你一定会发现它不正确的地方:government 模块和其中的函数都是私有(private)的,你不被允许访问它们。


访问权限

Rust 中有两种简单的访问权:公共(public)和私有(private)。

默认情况下,如果不加修饰符,模块中的成员访问权将是私有的。

如果想使用公共权限,需要使用 pub 关键字。

对于私有的模块,只有在与其平级的位置或下级的位置才能访问,不能从其外部访问。

实例

mod nation {pub mod government {pub fn govern() {}}mod congress {pub fn legislate() {}}mod court {fn judicial() {super::congress::legislate();}}
}fn main() {nation::government::govern();
}

这段程序是能通过编译的。请注意观察 court 模块中 super 的访问方法。

如果模块中定义了结构体,结构体除了其本身是私有的以外,其字段也默认是私有的。所以如果想使用模块中的结构体以及其字段,需要 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"),}}}
}
pub fn eat_at_restaurant() {let mut meal = back_of_house::Breakfast::summer("Rye");meal.toast = String::from("Wheat");println!("I'd like {} toast please", meal.toast);
}
fn main() {eat_at_restaurant()
}

运行结果:

I'd like Wheat toast please

枚举类枚举项可以内含字段,但不具备类似的性质:

实例

mod SomeModule {pub enum Person {King {name: String},Queen}
}fn main() {let person = SomeModule::Person::King{name: String::from("Blue")};match person {SomeModule::Person::King {name} => {println!("{}", name);}_ => {}}
}

运行结果:

Blue

难以发现的模块

使用过 Java 的开发者在编程时往往非常讨厌最外层的 class 块——它的名字与文件名一模一样,因为它就表示文件容器,尽管它很繁琐但我们不得不写一遍来强调"这个类是文件所包含的类"。

不过这样有一些好处:起码它让开发者明明白白的意识到了类包装的存在,而且可以明确的描述类的继承关系。

在 Rust 中,模块就像是 Java 中的类包装,但是文件一开头就可以写一个主函数,这该如何解释呢?

每一个 Rust 文件的内容都是一个"难以发现"的模块。

让我们用两个文件来揭示这一点:

main.rs 文件

// main.rs
mod second_module;fn main() {println!("This is the main module.");println!("{}", second_module::message());
}

second_module.rs 文件

// second_module.rs
pub fn message() -> String {String::from("This is the 2nd module.")
}

运行结果:

This is the main module.
This is the 2nd module.

use 关键字

use 关键字能够将模块标识符引入当前作用域:

实例

mod nation {pub mod government {pub fn govern() {}}
}use crate::nation::government::govern;fn main() {govern();
}

这段程序能够通过编译。

因为 use 关键字把 govern 标识符导入到了当前的模块下,可以直接使用。

这样就解决了局部模块路径过长的问题。

当然,有些情况下存在两个相同的名称,且同样需要导入,我们可以使用 as 关键字为标识符添加别名:

实例

mod nation {pub mod government {pub fn govern() {}}pub fn govern() {}
}use crate::nation::government::govern;
use crate::nation::govern as nation_govern;fn main() {nation_govern();govern();
}

这里有两个 govern 函数,一个是 nation 下的,一个是 government 下的,我们用 as 将 nation 下的取别名 nation_govern。两个名称可以同时使用。

use 关键字可以与 pub 关键字配合使用:

实例

mod nation {pub mod government {pub fn govern() {}}pub use government::govern;
}fn main() {nation::govern();
}

引用标准库

Rust 官方标准库字典:List of all items in this crate

在学习了本章的概念之后,我们可以轻松的导入系统库来方便的开发程序了:

实例

use std::f64::consts::PI;fn main() {println!("{}", (PI / 2.0).sin());
}

运行结果:

1

所有的系统库模块都是被默认导入的,所以在使用的时候只需要使用 use 关键字简化路径就可以方便的使用了。

这篇关于Rust组织管理,箱Crate包Package和模块module定义和区别,use关键字作用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/770304

相关文章

python: 多模块(.py)中全局变量的导入

文章目录 global关键字可变类型和不可变类型数据的内存地址单模块(单个py文件)的全局变量示例总结 多模块(多个py文件)的全局变量from x import x导入全局变量示例 import x导入全局变量示例 总结 global关键字 global 的作用范围是模块(.py)级别: 当你在一个模块(文件)中使用 global 声明变量时,这个变量只在该模块的全局命名空

深入探索协同过滤:从原理到推荐模块案例

文章目录 前言一、协同过滤1. 基于用户的协同过滤(UserCF)2. 基于物品的协同过滤(ItemCF)3. 相似度计算方法 二、相似度计算方法1. 欧氏距离2. 皮尔逊相关系数3. 杰卡德相似系数4. 余弦相似度 三、推荐模块案例1.基于文章的协同过滤推荐功能2.基于用户的协同过滤推荐功能 前言     在信息过载的时代,推荐系统成为连接用户与内容的桥梁。本文聚焦于

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

软考系统规划与管理师考试证书含金量高吗?

2024年软考系统规划与管理师考试报名时间节点: 报名时间:2024年上半年软考将于3月中旬陆续开始报名 考试时间:上半年5月25日到28日,下半年11月9日到12日 分数线:所有科目成绩均须达到45分以上(包括45分)方可通过考试 成绩查询:可在“中国计算机技术职业资格网”上查询软考成绩 出成绩时间:预计在11月左右 证书领取时间:一般在考试成绩公布后3~4个月,各地领取时间有所不同

安全管理体系化的智慧油站开源了。

AI视频监控平台简介 AI视频监控平台是一款功能强大且简单易用的实时算法视频监控系统。它的愿景是最底层打通各大芯片厂商相互间的壁垒,省去繁琐重复的适配流程,实现芯片、算法、应用的全流程组合,从而大大减少企业级应用约95%的开发成本。用户只需在界面上进行简单的操作,就可以实现全视频的接入及布控。摄像头管理模块用于多种终端设备、智能设备的接入及管理。平台支持包括摄像头等终端感知设备接入,为整个平台提

native和static native区别

本文基于Hello JNI  如有疑惑,请看之前几篇文章。 native 与 static native java中 public native String helloJni();public native static String helloJniStatic();1212 JNI中 JNIEXPORT jstring JNICALL Java_com_test_g

从状态管理到性能优化:全面解析 Android Compose

文章目录 引言一、Android Compose基本概念1.1 什么是Android Compose?1.2 Compose的优势1.3 如何在项目中使用Compose 二、Compose中的状态管理2.1 状态管理的重要性2.2 Compose中的状态和数据流2.3 使用State和MutableState处理状态2.4 通过ViewModel进行状态管理 三、Compose中的列表和滚动

Spring 源码解读:自定义实现Bean定义的注册与解析

引言 在Spring框架中,Bean的注册与解析是整个依赖注入流程的核心步骤。通过Bean定义,Spring容器知道如何创建、配置和管理每个Bean实例。本篇文章将通过实现一个简化版的Bean定义注册与解析机制,帮助你理解Spring框架背后的设计逻辑。我们还将对比Spring中的BeanDefinition和BeanDefinitionRegistry,以全面掌握Bean注册和解析的核心原理。

Android fill_parent、match_parent、wrap_content三者的作用及区别

这三个属性都是用来适应视图的水平或者垂直大小,以视图的内容或尺寸为基础的布局,比精确的指定视图的范围更加方便。 1、fill_parent 设置一个视图的布局为fill_parent将强制性的使视图扩展至它父元素的大小 2、match_parent 和fill_parent一样,从字面上的意思match_parent更贴切一些,于是从2.2开始,两个属性都可以使用,但2.3版本以后的建议使

Collection List Set Map的区别和联系

Collection List Set Map的区别和联系 这些都代表了Java中的集合,这里主要从其元素是否有序,是否可重复来进行区别记忆,以便恰当地使用,当然还存在同步方面的差异,见上一篇相关文章。 有序否 允许元素重复否 Collection 否 是 List 是 是 Set AbstractSet 否