Rust中箱、包和模块的学习笔记

 更新时间:2024年03月14日 10:11:43   作者:希望_睿智  
Rust中有三个重要的组织概念:箱、包、模块,本文主要介绍了Rust中箱、包和模块的学习笔记,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧
(福利推荐:【腾讯云】服务器最新限时优惠活动,云服务器1核2G仅99元/年、2核4G仅768元/3年,立即抢购>>>:9i0i.cn/qcloud

(福利推荐:你还在原价购买阿里云服务器?现在阿里云0.8折限时抢购活动来啦!4核8G企业云服务器仅2998元/3年,立即抢购>>>:9i0i.cn/aliyun

概述

Rust语言使用模块系统来组织工程和代码。模块系统允许我们将相关的函数、类型、常量等组织在一起,形成一个逻辑上的单元。通过模块系统,我们可以隐藏实现细节,只暴露必要的接口,从而提高代码的可读性和可维护性。Rust的模块系统还支持路径依赖和重导出等功能,使得代码的组织更加灵活和方便。

Rust的模块系统中有三个非常重要的概念,分别是:箱(Crate)、包(Package)和模块(Module),下面逐一进行介绍。

箱(Crate)

箱,英文为Crate,是Rust中的编译单元和构建单元,也是Cargo打包和分发的基本单位。Crate可以是库(library crate),也可以是二进制程序(binary crate)。库crate包含了可以被其他crate使用的代码,二进制crate则包含了可以执行的程序。每个crate都有一个crate root,它是编译器开始构建crate模块树的源文件。对于库crate,crate root通常是src/lib.rs文件;对于二进制crate,crate root通常是src/main.rs文件。

通过crate,我们可以将代码进一步拆分成更小的、更易于管理和维护的单元。当在Cargo中创建一个新的项目时,实际上就是在创建一个Crate。通过cargo new my_crate命令,Cargo将为我们初始化一个新的Crate结构,其中包括:源码目录、测试文件、Cargo.toml配置文件等。在Rust中,Crate是编译时的概念,它指代的是编译后生成的一个单元,可以是一个库或者一个可执行程序。

包(Package)

包,英文为Package,是Cargo用于组织和构建代码的基本单位。每个Rust项目都包含至少一个Package,并通过名为Cargo.toml的配置文件来描述其属性和依赖关系。Package的元数据存储在Cargo.toml文件中,这个文件包含了关于Package的基本信息,比如:名称、版本、作者、描述、许可证等。另外,Cargo.toml还列出了Package的依赖项,这些依赖项是其他Packages或Crates,它们会被Cargo自动下载和构建。

Package通常包含源码目录,包括但不限于src目录下的main.rs或lib.rs。如果项目更复杂,还可以有多个模块文件和子模块文件夹。一个Package可以包含一个或多个Crates,但通常情况下,一个简单的Package会对应一个单一的Crate。当通过cargo build命令构建项目时,最终输出的二进制文件或库文件就是这个Crate。

模块(Module)

模块,英文为Module,是用于在crate内部进行分层和封装的机制。模块内部又可以包含模块,从而形成一个树形结构,也称为模块树。每个crate会自动产生一个与当前crate同名的模块,作为这个树形结构的根节点。模块是元素(比如:函数、结构体、trait等)的集合,是一种抽象的概念,而文件则是承载这个概念的实体。

在Rust中,创建新模块主要有以下三种方式。

1、在一个文件中创建内嵌模块。这可以通过直接使用mod关键字来实现,模块的内容会被包含在大括号内部。

2、独立的一个文件就是一个模块,文件名即是模块名。

3、一个文件夹也可以代表一个模块。在这种情况下,有两种方法可以实现:

(1)文件夹内部需要有一个名为mod.rs的文件,这个文件就是这个模块的入口。在rustc 1.30版本之前,这是唯一的方法。

(2)在文件夹同级目录里创建一个与模块(文件夹)同名的rs文件。在rustc 1.30版本之后,更建议使用这样的命名方式,以避免项目中存在大量同名的mod.rs文件。

模块树

模块树是一个逻辑上的分层结构,它反映了源代码文件的组织方式。每个Rust项目都可以看作一个模块树的根,其中包含零个或多个子模块。每个模块可以进一步包含其他的子模块,从而形成嵌套的层次结构。

在下面的示例模块树中,lib.rs是crate的根模块,shapes和math是它的子模块。circle和rectangle是shapes的子模块,algebra和geometry是math的子模块。shapes之所以是模块,是因为shapes文件夹下有一个mod.rs文件。math之所以是模块,是因为math同级目录下有一个同名的math.rs文件。在后面内容的介绍当中,我们也会用到这里的示例模块树。

project/
├── src/
│   ├── lib.rs             // crate根模块
│   ├── shapes/
│   │   ├── mod.rs         // shapes模块
│   │   ├── circle.rs
│   │   └── rectangle.rs
│   ├── math/
│   │   ├── algebra.rs
│   │   └── geometry.rs
│   └── math.rs           // math模块

模块路径

在Rust中,模块路径是用于唯一标识模块中定义的元素(比如:函数、结构体等)的字符串。模块路径由一系列由双冒号(::)分隔的标识符组成,从crate根开始,一直到指定的项,可以是绝对路径或相对路径。

绝对路径:以crate::开始,表示从crate根开始的完整路径。在下面的示例代码中,crate::shapes::circle::Area表示从crate根开始的shapes子模块、circle子目录的Area函数。

use crate::shapes::circle::Area;

相对路径:直接使用模块名称表示同级模块,或者相对于当前模块的子模块。有两个特殊的标识需要记住,self::表示当前模块,super::表示当前模块的父模块。

// 在shapes/mod.rs中引用circle.rs中的内容
use self::circle::Area;

// 在circle.rs中引用shapes/mod.rs中定义的公共常量DEFAULT_RADIUS
use super::DEFAULT_RADIUS;

// 在同一目录下引用rectangle模块
use rectangle::Rectangle;

访问权限

在Rust中,访问权限是通过pub关键字来控制的。默认情况下,如果不加修饰符,模块中的成员访问权将是私有的。这意味着,它们只能在定义它们的模块内部被访问。如果想让其他模块能够访问某个成员,就需要在该模块和该成员前加上pub关键字来声明其为公开的。

访问权限主要有两种:一种是模块级的访问权限,另一种是成员级别的访问权限。

1、模块级的访问权限。公开模块可以在任何地方被访问,只要我们知道正确的路径。私有模块只能在与其平级的位置,或下级的位置被访问。也就是说,如果一个模块是私有的,那么只有在其同级模块或子模块中才能引用它。

2、成员级别的访问权限。使用pub关键字标记的成员是公开的,可以在其他模块中通过路径来访问。没有使用pub关键字标记的成员是私有的,只能在定义它们的模块内部访问。

// 公开模块
pub mod public_module {
    // 公开函数,可以在其他模块中访问
    pub fn public_function() {
    }
  
    // 私有函数,只能在本模块内部访问
    fn private_function() {
    }
}

// 私有模块
mod private_module {
    // 这个模块是私有的,不能在其他模块中直接访问
    fn private_function() {
    }
}

fn main() {
    public_module::public_function();
}

除此之外,Rust还提供了更细粒度的访问控制,允许我们指定一个成员仅在crate内部可见,或者仅在特定的模块及其子模块中可见。pub(crate)表示该成员在当前crate的任何地方都可见,但在外部crate中不可见。pub(in module)表示该成员在指定的模块及其子模块中可见,在其他模块不可见。

// 函数仅在当前crate内可见
pub(crate) fn crate_function() {
}

// 公开模块
pub mod my_module {
    // 函数仅在当前模块及其子模块中可见
    pub(in crate::my_module) fn module_function() {
    }

    pub fn public_function() {
        // 可以调用crate_function
        crate::crate_function();

        // 可以调用module_function
        module_function();
    }
}
  
// 另一个模块
mod another_module {
    pub fn another_function() {
        crate::crate_function();
        // 下面的代码会提示编译错误:function `module_function` is private
        super::my_module::module_function();
    }
}

fn main() {
    crate_function();
}

如果模块中定义了结构体,那么结构体本身以及它的字段默认都是私有的。如果希望结构体的某个字段能够被外部访问,则需要在结构体和该字段前均加上pub关键字。枚举类型则不同,只需要在枚举类型前加上pub关键字,而不需要在枚举成员前加上pub关键字。

使用use

use关键字用于导入模块或库中的元素(比如:函数、结构体等),以便在当前作用域中使用它们而无需使用完全限定的名称。use语句通常放在文件的顶部,紧接在模块声明之后。

use关键字的使用方式主要以下几种。

1、导入整个模块。可以使用use来导入整个模块,这样我们就可以直接使用该模块中公开的成员。

// 导入std模块中的vec模块
use std::vec;

fn main() {
    // 直接使用vec!宏
    let value = vec![1, 2, 3];
    println!("{:?}", value);
}

2、导入特定项。可以使用use来导入模块中的特定项,而不是整个模块。

// 只导入HashMap
use std::collections::HashMap;

3、重命名导入的项。如果导入的元素在当前作用域中已经存在同名项,或者想要使用不同的名称来引用它,我们可以使用as关键字来重命名。

// 重命名HashMap为:MyMap
use std::collections::HashMap as MyMap;

4、使用通配符导入。使用*可以导入模块中所有公开的成员,但需要注意的是,过度使用通配符导入可能会导致名称冲突和不可预见的行为,因此通常建议明确导入你需要的元素。

// 导入std::collections模块中的所有公开成员
use std::collections::*;

5、多个use语句可以组合在一起,以提高便捷性和可读性。

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

总结

Rust的模块系统是其代码组织管理的核心部分,它提供了一种方式来封装和组织代码,控制作用域和路径的私有性,以及导出公共接口。模块系统使得开发者能够构建大型、复杂的应用程序,同时保持代码的清晰性和可维护性。

到此这篇关于Rust中箱、包和模块的学习笔记的文章就介绍到这了,更多相关Rust 箱、包和模块内容请搜索程序员之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持程序员之家!

相关文章

  • 详解Rust中泛型的使用

    详解Rust中泛型的使用

    泛型是一种在编写代码时不指定具体类型,而在使用时再确定类型的编程技巧,本文将详细介绍?Rust?中泛型的相关概念和用法,希望对大家有所帮助
    2023-06-06
  • Rust裸指针的安全性实例讲解

    Rust裸指针的安全性实例讲解

    裸指针是一个不包含所有权和借用关系的原始指针,它们与常规指针相比没有任何限制和保护措施,这篇文章主要介绍了Rust裸指针的安全性实例,需要的朋友可以参考下
    2023-05-05
  • 如何使用Rust写个猜数字游戏

    如何使用Rust写个猜数字游戏

    这篇文章主要介绍了Rust写个猜数字游戏,本项目通过动手实践,介绍了Rust新概念:let、match、函数、使用外部 crate 等,接下来的文章,你会继续深入学习这些概念,并且介绍大部分编程语言都有的概念,如变量、数据类型和函数,以及如何在 Rust 中使用它们,需要的朋友可以参考下
    2023-12-12
  • 解析rust中的struct

    解析rust中的struct

    自定义的数据类型,为相关联的值命名,打包成有意义的组合,类似python的dict,但是赋值的时候可以不按顺序,本文给大家介绍下rust中的struct知识,感兴趣的朋友一起看看吧
    2022-10-10
  • Rust初体验:手把手教你构建‘Hello,?World!’

    Rust初体验:手把手教你构建‘Hello,?World!’

    "准备好了吗?一起踏上Rust编程语言的精彩旅程!在这篇「Rust初体验」中,我们将手把手教你构建经典程序“Hello,?World!”,感受Rust的强大与安全,短短几行代码,就能让你对这个系统级语言的魅力一探究竟!快加入吧,惊喜等你发现!"
    2024-01-01
  • 使用Rust语言编写一个ChatGPT桌面应用示例详解

    使用Rust语言编写一个ChatGPT桌面应用示例详解

    这篇文章主要介绍了如何用Rust编写一个ChatGPT桌面应用,文中有详细的流程介绍,对大家的学习或工作有意一定的帮助,需要的朋友可以参考下
    2023-05-05
  • Rust中Cargo的使用详解

    Rust中Cargo的使用详解

    Cargo 是 Rust 的构建系统和包管理器,?多数 Rustacean 们使? Cargo 来管理他们的 Rust 项?,因为它可以为你处理很多任务,?如构建代码、下载依赖库并编译这些库,这篇文章主要介绍了Rust中Cargo的使用,需要的朋友可以参考下
    2022-11-11
  • R语言ggplot2绘图安装与调试

    R语言ggplot2绘图安装与调试

    ggplot2是R语言中最常用的绘图包之一,它提供了一种基于图层的绘图语法,使得用户可以轻松地创建高质量的数据可视化图表。在使用ggplot2之前,需要先安装该包并进行调试。安装ggplot2可以通过CRAN或GitHub进行,调试则需要注意数据格式、语法错误等问题。
    2023-06-06
  • rust延迟5秒锁屏的实现代码

    rust延迟5秒锁屏的实现代码

    这篇文章主要介绍了rust延迟5秒锁屏的实现代码,文中通过实例代码也介绍了rust计算程序运行时间的方法,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09
  • 关于rust的模块引入问题

    关于rust的模块引入问题

    Rust 语言是一种高效、可靠的通用高级语言,它的执行效率也是令人称赞的,是一种少有的兼顾开发效率和执行效率的语言,这篇文章主要介绍了rust的模块引入相关知识,需要的朋友可以参考下
    2022-10-10

最新评论

?


http://www.vxiaotou.com