Rust基础学习-ModulesPackage

news2025/2/24 9:25:46

在Rust中,模块有助于将程序分割成逻辑单元,以提高可读性和组织性。一旦程序变得更大,将其拆分为多个文件或命名空间非常重要。

模块有助于构建我们的程序。模块是项目的集合:包括函数、结构体甚至其他模块。

cargo


Module

定义模块

Rust中,可以使用mod关键字来定义一个模块,语法如下:

mod module_name {
  // code
}

这里,module_name 是模块的名称。看下面的例子;

mod config {
    fn print() {
        println!("config!");
    }
}

上面的示例中,我们使用mod定义了以config为名称的一个模块。在模块内部,我们定义 了一个简单的函数print;


Rust 模块内项目的可见性

模块中的项目可以是私有的或公共的。默认情况下,模块是私有的。

这意味着模块内部的项目无法在模块外部访问。pub 关键字可用于使项目具有公共可见性。让我们看一个示例。

mod config {
    // items in modules by default have private visibility
    fn select() {
        println!("called config::select");
    }

    // use the `pub` keyword to override private visibility
    pub fn print() {
        println!("called config::print");
    }
}

在这里,我们定义一个名为config的模块,其中包含两个函数select()print()

print()函数以pub关键字开头,这意味着它具有公共可见性。但select()函数则没有。

如果你此时运行程序会发现有一些警告,这是因为我们并没有调用这些函数,现在,我们尝试调用一下;

mod config {
    // items in modules by default have private visibility
    fn select() {
        println!("called config::select");
    }

    // use the `pub` keyword to override private visibility
    pub fn print() {
        println!("called config::print");
    }
}

fn main() {
    // public items inside module can be accessed outside the parent module
    // call public print function from display module
    config::print();
}

在这里,我们使用config::print()语法来调用 config 模块内的公共函数 print():: 运算符用于分隔模块名称和要在模块内调用的项目。

但是,模块内部的私有项目不可在模块外部访问。如果我们尝试在 config 模块内调用私有函数 select(),将会收到编译错误。


注意:当在模块内部某个用pub修饰的方法调用模块内部非pub方法时,我们在调用该pub方法时,其涉及到的非pub方法也将具有pub性质;

我们看个例子:

mod player {
    // private function
    fn focus() {
        println!("called player::focus");
    }

    // public function
    pub fn shift() {
        println!("called player::shift");
    }

    // public function
    pub fn jump() {
        // call private function focus and shift inside the module
        focus();
        shift();
        println!("called player::jump");
    }
}

fn main() {
    // call public function jump from player module
    player::jump();
}

called player::focus
called player::shift
called player::jump

在这里,我们在player模块内定义了多个函数。请注意,我们能够在同一模块内的另一个函数jump()中调用私有函数focus()


模块嵌套

一个模块中还可以在定义其他模块,这就是模块的嵌套;看例子:

// nested module
pub mod player {
    pub mod sprite {
        pub fn create() {
            println!("called player::sprite::create");
        }
    }
}

fn main() {
    // call public function create from sprite module which is inside player module 
    player::sprite::create();
}

输出:

called player::sprite::create

在这里,我们将一个 sprite 模块嵌套在 player 模块内部。我们在 sprite 模块内定义了一个名为 create() 的公共函数,在 main() 函数中通过 player::sprite::create() 调用。


use关键字

我们可以使用use关键字将模块内的项目引入当前作用域。use关键字帮助我们消除调用函数时写出完整模块路径的需要。让我们通过使用use关键字来重新编写我们的嵌套模块示例。

// nested module
pub mod player {
    pub mod sprite {
        pub fn create() {
            println!("called player::sprite::create");
        }
    }
}

// bring the create function into scope
use player::sprite::create;

fn main() {
    // call public function directly
    create();
}

这里,我们使用 use 关键字从 player 模块内部的 sprite 模块中将 create() 函数引入当前作用域。

这样我们可以直接调用 create() 函数,而不需要完全限定名称为 player::sprite::create()。


Crate和Package

一个 crate 可以包含一个或多个 Rust 模块,这些模块可以包含诸如函数、类型和常量之类的代码。

一个 crate 有两种类型:二进制 crate 和库 crate。二进制 crate 是一个 Rust 程序,编译成一个可执行文件或多个可执行文件,并且每个可执行文件都有一个 main() 函数。

crate 不会编译成可执行文件,也没有 main() 函数。库 crate 通常定义了可以在多个项目中使用的共享功能。Crates 可以捆绑在一起形成一个 package


可以使用内置在Rust中的Cargo软件包管理器来创建软件包。 Cargo与Rust一起预安装。我们可以使用 cargo 来创建一个软件包。一个软件包包含一个或多个提供一组功能的crate。

一个包中可以包含许多二进制 crate,但最多只能包含一个库 crate。


创建二进制包

要创建一个二进制包,我们可以在终端中使用 cargo 命令。

$ cargo new hello_world --bin

我们使用 cargo --bin选项创建一个二进制包 hello_world。 这是 cargo 的默认行为。 让我们来看看 hello_world 包的内容。

hello_world
├── Cargo.toml
└── src
    └── main.rs
  • hello_world 是包目录
  • Cargo.toml 是一个包含有关 crate 的元数据的文件,如其名称、版本和依赖项
  • src/main.rs crate 根目录,包含二进制包的源代码

创建库包

$ cargo new hello_world_lib --lib

包结构如下:

hello_world_lib
├── Cargo.toml
└── src
    └── lib.rs
  • hello_world_lib 是包目录
  • Cargo.toml 是一个包含有关包的元数据的文件,例如其名称、版本和依赖关系
  • src/lib.rs 是 crate 根目录,包含库包的源代码

一个包可以包含src/main.rssrc/lib.rs。在这种情况下,它有两个 crate:一个二进制 crate 和一个库 crate,两者都与包的名称相同。例如,

hello_world
├── Cargo.toml
└── src
    └── lib.rs
    └── main.rs

Cargo包管理器

Cargo

CargoRust的包管理器。它与Rust一起预装,并可用于打包依赖项,管理它们以及构建和分发我们自己的包/库。

cargo的特点:

  • 依赖管理

Cargo 可轻松管理我们项目的依赖项,包括添加、更新和删除依赖项。
构建和打包

Cargo 可自动构建和打包我们的 Rust 项目,创建可与他人共享的二进制或库代码。

  • 文档生成

Cargo 可自动为我们的代码生成文档,使其他开发人员更容易理解和使用我们的库。

  • 下载 crate

Cargo 可从 crates.io 下载并安装库,这是 Rust crate 的中央存储库。

  • 运行二进制或测试

Cargo 可构建我们的源代码,运行可执行二进制文件,并运行我们的测试。


依赖管理

Cargo 的主要功能之一是可以下载、管理外部库。让我们看看如何从 crates.io 使用外部 crate 的示例。crates.io 是一个中央仓库,我们可以从中获取和发布用于 Rust 的共享库。

  • 创建一个项目
$ cargo new hello_world
  • 添加一个生成随机数的依赖rand,我们可以在cargo.toml中的[dependencies]部分进行添加
name = "hello_world"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
rand = "0.8.5"

我们还可以使用命令 cargo add rand 来为我们的项目添加依赖。

注意,如果通过命令的方式添加依赖,在添加时Rust就会加载编译该依赖,而通过cargo.toml手动添加时,程序会在你首次运行程序时进行加载编译的操作。

  • 使用依赖
use rand::Rng;

fn main() {
    let mut rng = rand::thread_rng();

    // simulate rolling a die
    println!("roll = {}", rng.gen_range(1..=6));
}

# Output: roll = 5

构建和执行

Rust支持使用cargo命令对程序进行buildrun.命令分别是

  • cargo build
  • cargo run

一般情况下,执行cargo run时,默认会自动执行cargo build,所以一般我们需要运行程序时不需要先执行build,再执行run,而是直接执行cargo run即可。

常用命令一览表:

CommandDescription
cargo newCreate a new Rust project with basic directory structure
cargo buildBuild (compile) the current project and generate a binary executable
cargo runBuild and run your current project (cargo build + run)
cargo checkBuild the current project without generating a binary executable
cargo addAdd a new dependency and include it in Cargo.toml file
cargo updateUpdate all dependencies of current project to latest version

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

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

相关文章

嵌入式硬件VS软件,到底哪个更难?

在嵌入式系统开发中,硬件和软件是密不可分的两个方面。但是,究竟是硬件开发更具挑战性,还是软件开发更难以应对呢?本文将就这一问题展开讨论,探究嵌入式硬件和软件在开发过程中的各种挑战与特点。 一、硬件开发&#…

12.实战私有数据微调ChatGLM3

实战私有数据微调ChatGLM3 实战私有数据微调ChatGLM3实战构造私有的微调数据集基于 ChatGPT 设计生成训练数据的 Prompt使用 LangChain GPT-3.5-Turbo 生成训练数据样例训练数据解析、数据增强和持久化存储自动化批量生成训练数据集流水线提示工程(Prompt Engineer…

HTTPS请求阶段图解分析

HTTPS请求阶段分析 请求阶段分析 请求阶段分析 一个完整、无任何缓存、未复用连接的 HTTPS 请求需要经过以下几个阶段: DNS 域名解析、TCP 握手、SSL 握手、服务器处理、内容传输。 一个 HTTPS 请求共需要 5 个 RTT 1 RTT(域名解析) 1 RTT…

element table 点击某一行中按钮加载

在Element UI中,实现表格(element-table)中的这种功能通常涉及到数据处理和状态管理。当你点击某一行的按钮时,其他行的按钮需要动态地切换为加载状态,这可以通过以下步骤实现: 1.表格组件:使用…

NodeClub:NodeJS构造开源交流社区

NodeClub: 连接每一个想法,NodeClub让社区更生动- 精选真开源,释放新价值。 概览 NodeClub是一个基于Node.js和MongoDB构建的社区系统,专为开发者和社区爱好者设计。它提供了一套完整的社区功能,包括用户管理、内容发…

基于 Nginx Ingress + 云效 AppStack 实现灰度发布

作者:子丑 场景简介 灰度发布是降低生产部署风险,提升线上服务稳定性的重要手段,这在当前快速迭代的软件研发中尤为重要。相对于 K8s 默认的滚动部署或者简单的 Pod 分批,基于流量特征的灰度发布验证更精准,风险更低…

安鸾学院靶场——安全基础

文章目录 1、Burp抓包2、指纹识别3、压缩包解密4、Nginx整数溢出漏洞5、PHP代码基础6、linux基础命令7、Mysql数据库基础8、目录扫描9、端口扫描10、docker容器基础11、文件类型 1、Burp抓包 抓取http://47.100.220.113:8007/的返回包,可以拿到包含flag的txt文件。…

buuctf----warmup_csaw_2016

进来医院先来一套常规检查 啥保护都没,看大佬说基本栈溢出 CT一看 OK cat flag 更喜欢了 40060D 找到地址 get也来了,稳啦! 0x80-0x40 8 根据上道题的exp from pwn import * ghust remote("node5.buuoj.cn",27229) addr 0x40060D payload bA * 0x40 bB*8…

SpringMVC-基础架构

一、什么是MVC 二、什么是SpringMVC 三、SpringMVC的特点 四、配置SpringMVC 简单流程&#xff1a; 总体框架 1.创建pom.xml依赖 <!--打包方式--><packaging>war</packaging><!--依赖--><dependencies><dependency><groupId>org.s…

路由器怎么设置局域网?

局域网&#xff08;Local Area Network&#xff0c;LAN&#xff09;是指在一个相对较小的地理范围内&#xff0c;如家庭、办公室或学校等&#xff0c;通过路由器等设备连接起来的计算机网络。设置局域网可以方便地实现内部资源共享和信息交流。本文将介绍如何设置局域网以及一个…

C# 设置PDF表单不可编辑、或提取PDF表单数据

PDF表单是PDF中的可编辑区域&#xff0c;允许用户填写指定信息。当表单填写完成后&#xff0c;有时候我们可能需要将其设置为不可编辑&#xff0c;以保护表单内容的完整性和可靠性。或者需要从PDF表单中提取数据以便后续处理或分析。 之前文章详细介绍过如何使用免费Spire.PDF…

晶振的匹配电容的计算

晶振 等效电路 C0是晶振的静态电容 L1是晶振的等效电感 C1是晶振的等效电容 R1是晶振的等效串联电阻 芯片内部已有反相器和负载电阻 计算公式 参考1 参考2

maven 显式依赖包包含隐式依赖包,引起依赖包冲突

问题&#xff1a;FlinkCDC 3.0.1 代码 maven依赖包冲突 什么是依赖冲突 依赖冲突是指项目依赖的某一个jar包&#xff0c;有多个不同的版本&#xff0c;因而造成类包版本冲突 依赖冲突的原因 依赖冲突很经常是类包之间的间接依赖引起的。每个显式声明的类包都会依赖于一些其它…

Mongodb在UPDATE操作中使用$push向数组中插入数据

学习mongodb&#xff0c;体会mongodb的每一个使用细节&#xff0c;欢迎阅读威赞的文章。这是威赞发布的第69篇mongodb技术文章&#xff0c;欢迎浏览本专栏威赞发布的其他文章。如果您认为我的文章对您有帮助或者解决您的问题&#xff0c;欢迎在文章下面点个赞&#xff0c;或者关…

基数排序O(n)时间复杂度的实现

基数排序O(n)时间复杂度的实现 前言 之前写过一篇文章六种常见排序算法分析与实现&#xff0c;讲了六种常见的排序算法&#xff0c;但是没有了解到桶排序&#xff0c;基数排序这两种排序算法&#xff0c;今天刷LeetCode发现了这两种算法&#xff0c;本文先来聊聊基数排序的思…

前端 CSS 经典:在 Vue3 中使用渐进式图片

1. 什么是渐进式图片 当我们网站会加载很多图片的时候&#xff0c;有些图片尺寸很大&#xff0c;加载就会很慢&#xff0c;会导致页面长时间陷入白屏状态&#xff0c;用户体验很不好。所以可以使用渐进式图片&#xff0c;先给用户展示模糊图&#xff0c;这些图尺寸小&#xff…

数据分析-Excel基础函数的使用

Excel基础函数&#xff1a; sum:求和 sumif:单条件求和 sumifs:多条件求和 subtotal:根据筛选求和 if:逻辑判断 vlookup:连接匹配数据 match:查找数值在区域中的位置 index:根据区域的位置返回数值 match、index:一起使用&#xff1a;自动根据列名查找数据 sumifs、match、ind…

k8s+RabbitMQ单机部署

1 k8s 配置文件yaml: apiVersion: apps/v1 kind: Deployment metadata:name: rabbitmq-deploynamespace: rz-dt spec:replicas: 1selector:matchLabels:app: rabbitmqtemplate:metadata:labels:app: rabbitmqspec:containers:- name: rabbitmqimage: "rz-dt-image-server…

ubtun虚拟机安装

选择镜像后启动 选择第一个回车 加载完成后 &#xff0c;进入Ubuntu安装界面&#xff0c;安装语言选择English&#xff0c;完成后按一下回车&#xff1a; 此时弹出安装器可更新提示&#xff0c;下方选项选择第二个Continue without updating&#xff08;不更新&#xff0c;继续…

计算机网络 —— 应用层(应用层概述及服务方式)

计算机网络 —— 应用层&#xff08;应用层概述及服务方式&#xff09; 应用层服务方式C/S&#xff08;客户端-服务器&#xff08;C/S&#xff09;模型&#xff09;基本概念特点B/S&#xff08;Browser/Server&#xff09;基本概念特点应用场景 p2p &#xff08;对等网络&#…