《Rust权威指南》学习笔记(二)

news2025/1/7 13:37:43
枚举enum

1.枚举的定义和使用如下图所示:

定义时还可以给枚举的成员指定数据类型,例如:enum IpAddr{V4(u8, u8, u8, u8),V6(String),}。枚举的变体都位于标识符的命名空间下,使用::进行分隔。

2.一个特殊的枚举Option(在预导入模块prelude中定义),它描述了某个值可能存在(某种类型)或者不存在的情况,Rust中没有Null。

3.控制流运算符match:允许一个值与一系列模式进行匹配,并执行匹配的模式对应的代码,模式可以是字面值、变量名、通配符等等。match表达式类似于一个函数,每个分支都会有一个返回值,并且整个match表达式的返回值类型必须一致。如下图:

Match匹配必须穷举所有的可能,否则会报错,可以用通配符_(这里可以用任何一个合法标识符来捕获剩下的匹配值)替代其余没有列出的值,_需要写在最后面,也可以使用任何合法的变量名捕获其他所有情况,后续可以在分支内部使用该变量进行进一步的处理。

4.if let的用法:处理只关心一种匹配而忽略其他匹配的情况,下图中v 恰好等于Some(3) 时,条件会成立,第一个分支就会被执行。if let还可以用于简化模式匹配,用于匹配并解构Option,、Result等枚举类型的某个特定变体,并在匹配成功时执行相应代码。

Rust代码组织

1.Package:是一个Rust项目的最外层单位,它由一个或多个crate组成(至少有一个)。它通常包含一个Cargo.toml文件,用于描述包的元数据、依赖项以及构建信息。每个package至少包含一个项目,这个项目可以是一个可执行项目(由main.rs文件定义)或者一个库项目(由lib.rs文件定义)。包和项目的关系是,一个package可以包含多个可执行项目(可放在src/bin目录下),但最多只能包含一个库项目。使用cargo new project创建一个新工程时,生成的就是一个Rust包(package)。想创建一个库包而不是可执行包,可以使用--lib选项。使用cargo new my_library --lib命令时,Cargo会在src/目录下创建一个lib.rs文件,而不是main.rs文件。这个lib.rs文件是库项目的入口文件,定义了库的公共API。

2.Crate:是Rust代码的编译单元,所有的Rust代码都是在crate的上下文中进行编译的。一个crate可以是一个库,也可以是一个可执行文件。每个crate都有一个根模块,根模块对应着crate的入口文件——对于库crate,入口文件是lib.rs,对于二进制crate,默认入口文件是main.rs(这个miain.rs编译生成的可执行文件名称与package名相同)。Crate定义了一个独立的命名空间,并且可以导入其他crate来使用它们的功能。由于main.rs是二进制crate的入口点,它的内容通常不会被库crate直接引用。因此,lib.rs中不能直接使用main.rs中定义的函数或结构体。相反,库crate应该定义功能,并将这些功能公开给其他模块或crate使用,而main.rs可以引用这些功能。

3.Module:是Rust中用于组织代码的机制,它允许将代码划分为多个部分,每个部分可以在其自己的命名空间中定义。模块帮助管理代码的可读性和可维护性,一个crate的根模块可以包含其他模块,而这些模块又可以嵌套定义子模块。Rust中的模块可以通过文件系统组织,例如,一个模块可以定义在与它同名的文件中,或者作为父模块文件中的嵌套模块定义,模块之间的关系通常通过use关键字和路径来引用。

4.Path:是Rust中用于引用项(例如函数、结构体、枚举、模块等)的方式,它定义了如何从一个命名空间访问另一个命名空间的内容。路径可以是绝对路径,从crate的根模块开始(可以使用crate名或者字面值“crate”);也可以是相对路径,从当前模块开始(使用self、super或当前模块的标识符,super用来访问父级模块路径中的内容,类似于文件系统中的..),路径的标识符之间用::隔开。路径使得你能够在模块层次结构中导航,访问不同模块和它们的内容。Rust的路径系统允许你清晰、简洁地访问代码片段,即使它们位于不同的模块或crate中。

5.私有边界:模块不仅可以组织代码,还可以定义私有边界,Rust中所有的条目(函数、方法、struct、enum、模块、常量等)默认都是私有的,父模块无法访问子模块中的私有条目,子模块可以使用所有祖先模块中的条目。可以使用pub来将这些条目声明为公有的,如下图,没有声明为公有的私有条目无法被访问:

6.use关键字:可以使用use关键字将路径(可以使用相对路径或者绝对路径)导作用域内(仍然遵循私有性规则),通常习惯将函数的父级模块引入作用域,以此来区分该函数是不是在其他模块引入的,而习惯将除函数外的其他元素如struct、enum等的整个完整路径引入作用域(如果有同名struct可以引用到父级以此来区分)。可以用as关键字来为引入的路径指定本地的别名,如:use std::fmt::Result as Re。

使用use将路径导入到作用域内后,该名称在此作用域中是私有的,可以在前面加上pub,则被导入的条目就可以被其他外部代码引入到他们的作用域中。如:pub use std::fmt::Result。

7.外部包的使用:需要现在Cargo.toml文件中添加依赖,然后用use将需要的特定条目引入到作用域内。标准库(std)也被当作外部包,不用在Cargo.toml文件中添加std,但需要用use将需要使用的std中的条目引入到当前作用域。当在Rust项目中使用cargo build命令编译程序时,Cargo(Rust的包管理器和构建系统)会将所有依赖的外部包下载并解压到target/debug/deps或target/release/deps文件夹中,具体位置取决于你是进行调试编译(debug)还是发布编译(release)。对于同一个包中的不同条目,可以使用嵌套路径的方式导入:路径相同的部分::{路径差异的部分}(路径差异部分用逗号分隔),如:use std::io::{cmp::Ordering,io};,如果两个use路径之一是另一个的子路径,可使用self,如:use std::io::{self,Write};。使用通配符*可以把路径中所有的公共条目都引入到作用域,如:use std::collections::*。

8.模块定义时,如果模块名后边是;,而不是代码块,Rust会从与模块同名的文件中加载内容,模块树的结构不会变化,如下图:

常见集合

1.Vector:由标准库提供,Vec<T>可以存储多个值,但只能存储相同类型的值,值在内存中连续存放。Vector初始化一般有两种方式,用new函数会初始化一个空的vector,还可以用宏定义vec!初始化,如下图所示:

向vector添加元素可以用push方法,例如v.push(1),添加的元素会被放在vector的末尾。当vector离开其作用域时,会像其他struct一样被清理掉,他里面所有的元素也会被清理掉。可以使用索引或者get方法来访问vector中的元素,get方法返回的是Option<T>枚举类型,所以当用get方法获取元素传入的索引越界时,返回的是None,而直接通过索引访问在越界时会引起panic。

所有权和借用规则在vector中同样适用,例如不能在同一作用域中同时拥有可变和不可变引用。可以用for循环来遍历vector中元素的值,如下图(println! 宏可以直接接受引用,所以不需要解引用i,就可以打印出其指向的值):

vector只能存储同一类型的数据,可以和enum配合使用来存储不同类型的值(将enum作为vector的元素),如下图:

2.字符串:字符串本质是Byte的集合,主要包括字符串字面值(&str)和String(由标准库提供,采用UTF-8编码)两种类型,Rust标准库还提供了其他字符串类型:OsString、OsStr、CString、CStr等。创建一个新的字符串可以使用new函数(如let mut s = String::new();),to_string()方法(可用于实现了Displaying trait的类型,包括字符串字面值)或者String::from()函数,如下图:

更新字符串的方式有:push_str()方法可以把一个字符串切片附加到String,如s.push_str(“abc”);表示将abc附加到s后面;push()方法可以把单个字符附加到String,如s.push(‘a’);;可以用+连接字符串,但只能把&str类型添加到String,即左侧操作数必须是String类型(左侧String的所有权会被消耗),右侧操作数必须是&str;format!可用来连接多个字符串(这种方式不会修改参数的所有权)。

String不支持索引的访问方式,可以将String看作是字节、标量或者字形,对于标量值可以用chars()方法来遍历,对于字节可以用bytes()方法来遍历。

可以使用[ ]和一个范围来创建字符串的切片,但如果切片跨越了字符边界就会报错(字符是以UTF-8编码的,有些字符占2-4个字节,切片的开始或结束位置不能在这样的2-4字节之间)。

3.HashMap<K,V>:以键值对的形式来存储数据,一个键对应一个值,Hash函数用来决定如何在内存中存放K和V。可以用new函数创建一个新的空HashMap(如let mut map = HashMap::new();),用insert方法向其中添加键值对(如map.insert("key1", "value1");)。在同一个HashMap中,所有的K必须是同一个类型,所有的V必须是同一个类型。还可以基于collect方法在元素类型为Tuple(要求Tuple有两个值,一个作为K,另一个作为V)的Vector上创建新的HahsMap,如下图:

在HashMap中,对于实现了Copy trait的类型(如i32),值会被复制到HashMap中,对于拥有所有权的值(如String),所有权会转移给HashMap,如果将值的引用插入到HashMap中,值的所有权不会转移,但在HashMap有效期间,被引用的值必须保持有效。可以用get方法传入参数K访问HashMap中的V,返回值为Option<T>枚举类型。可以用for遍历HashMap中的键值对,如下图:

更新HashMap有以下几种情况:1.K已经存在:可以选择替换现有的V、保留现有的V忽略新的V、合并现有的V和新的V;2.K不存在:添加一对KV。如果向HashMap插入一对KV,然后再插入同样的K不同的V则原来的V会被替换。可以先用entry方法检查指定的K是都存在(该方法返回enum Entry,代表值是否存在),然后使用Entry的or_insert()方法(若K存在,返回对应值的可变引用;若K不存在,该方法将参数作为K的新值插入HashMap,而后返回这个值的可变引用),如下图所示:

错误处理

1.Rust中将错误分为可恢复错误(例如文件未找到等,可再次尝试)和不可恢复错误(bug,例如索引访问越界),可恢复错误可返回Result<T,E>枚举类型,不可恢复错误和使用panic!宏来报错,这个宏的默认处理方式为展开(unwind)、清理调用栈,即从产生错误的地方开始,逆向遍历调用栈,逐层清理每一层函数调用所分配的资源。这个过程确保了所有已经获取的资源(例如内存、文件句柄、锁等)能够被正确地释放,避免资源泄漏。在展开过程中,Rust 会自动调用每个作用域中的析构函数(也称为Drop实现)释放资源或执行其他清理操作。然后退出程序。这样的默认操作比较费时,可以将其重新设置为panic!时直接中止调用栈,而不进行任何清理操作,内存清理交由操作系统去完成,具体设置可修改Cargon.toml文件,如下图:

panic!可能发生在我们自己写的程序中,也可能发生在我们程序所依赖的代码中,可以通过设置RUST_BACKTRACE环境变量回溯错误具体信息,如在运行时设置:cargo run RUST_BACKTRACE=1,但必须保证编译时没有加--realease选项。

2.Result枚举类型原始定义如下:

和Option一样,Result也是由prelude带入作用域,Result枚举类型可以作为函数返回值或match匹配结果,如下图:

3.unwrap()方法可用于从Option或Result类型中提取值。如果调用unwrap()时包含的值是Some或Ok,它将返回内部的值;如果是None或Err,它将触发恐慌(panic),程序会终止执行。expect()方法也用于从Option或Result类型中提取值,但与unwrap() 不同的是,它允许自定义panic时的错误消息。这样,当unwrap() 触发panic时,可以得到更明确的错误信息帮助调试。

4.错误处理的一种更加简洁和快捷的方式是使用?运算符,?运算符可以用于处理返回Result或Option类型的函数或表达式,如果Result是Ok,Ok中的值就是表达式的结果,然后继续执行程序;如果Result是Err,Err就是整个函数的返回值,相当于使用了return。如下图所示,从上到下代码逐渐简洁:

Trait std::convert::From上的from函数可以用于错误类型之间的转换,被?所应用的错误,会隐式地被from函数处理,当?调用from函数时,它所接收的错误类型会被转化为当前函数返回类型所定义的错误类型,只要每个错误类型实现了转换为所返回的错误类型的from函数。

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

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

相关文章

OSI模型的网络层中产生拥塞的主要原因?

&#xff08; 1 &#xff09;缓冲区容量有限&#xff1b;&#xff08; 1.5 分&#xff09; &#xff08; 2 &#xff09;传输线路的带宽有限&#xff1b;&#xff08; 1.5 分&#xff09; &#xff08; 3 &#xff09;网络结点的处理能力有限&#xff1b;&#xff08; 1 分…

linux上安装MySQL教程

1.准备好MySQL压缩包&#xff0c;并进行解压 tar -xvf mysql-5.7.28-1.el7.x86_64.rpm-bundle.tar -C /usr/local 2.检查是否有mariadb数据库 rpm -aq|grep mariadb 关于mariadb:是MySQL的一个分支&#xff0c;主要由开源社区在维护&#xff0c;采用GPL授权许可 MariaDB的目…

R语言中的时间序列分析·

1 数据集说明 AirPassengers 1949~1960年每月乘坐飞机的乘客数 JohnsonJohnson Johnson&Johnson每股季度收入 nhtemp 康涅狄格州纽黑文地区从1912年至1971年每年的平均气温 Nile 尼罗河的流量 sunspots 1749年~1983年月平均太阳黑子数 2 相关包 xts、forecast、tser…

LookingGlass使用

背景 Looking Glass 是一款开源应用程序&#xff0c;可以直接使用显卡直通的windows虚拟机。 常见环境是Linux hostwindows guest&#xff0c;基本部署结构图&#xff1a; 编译 git clone --recursive https://github.com/gnif/LookingGlass.git编译client mkdir client/b…

HCIA-Access V2.5_7_3_XG(S)原理_关键技术

为什么需要测距 因为上行链路只有一根纤,而且每一个ONU到OLT的距离是不一样的,虽然上行通过TDMA技术,让每一个ONU在不同的时间段发送数据,但是仍然有可能在同一时刻到达分光器,产生数据冲突。 有测距的信元传输 所以为了避免碰撞冲突,通过ONU在注册的时候就会启动测距…

四、VSCODE 使用GIT插件

VSCODE 使用GIT插件 一下载git插件与git Graph插件二、git插件使用三、文件提交到远程仓库四、git Graph插件 一下载git插件与git Graph插件 二、git插件使用 git插件一般VSCode自带了git&#xff0c;就是左边栏目的图标 在下载git软件后vscode的git插件会自动识别当前项目 …

RISC-V学习笔记

1.RISC ISA1个基本整数指令集多个可选的扩展指令集&#xff0c;如RV32I表示支持32位整数指令集。I表示基本指令集&#xff0c;M表示整数乘法与除法指令集&#xff0c;A表示存储器原子指令集&#xff0c;F表示单精度浮点指令集&#xff0c;D表示双精度浮点指令集等&#xff0c;C…

strapi中使用Documentation插件

Swagger UI 自动生成并展示了 API 的文档&#xff0c;这些文档是根据 OpenAPI Specification (OAS) 格式编写的。它提供了对 API 端点、请求方法&#xff08;GET, POST, PUT, DELETE 等&#xff09;、参数、响应格式等详细信息的描述 安装 npm run strapi install documentat…

AI来帮忙:蛋白纯化不用慌

在当今生物学研究的前沿领域&#xff0c;从探索疾病的发病机制&#xff0c;到新型药物的研发&#xff0c;再到生物工程产品的制造&#xff0c;高纯度、高活性的蛋白质都是不可或缺的基石。 科研人员在蛋白纯化的征程中&#xff0c;时常被诸多难题困扰。一方面&#xff0c;生物…

SpringCloud系列教程:微服务的未来(六)docker教程快速入门、常用命令

对于开发人员和运维工程师而言&#xff0c;掌握 Docker 的基本概念和常用命令是必不可少的。本篇文章将带你快速入门 Docker&#xff0c;并介绍一些最常用的命令&#xff0c;帮助你更高效地进行开发、测试和部署。 目录 前言 快速入门 docker安装 配置镜像加速 部署Mysql …

基于单片机中药存放环境监测系统的实现

基于单片机中药存放环境监测系统的实现 项目开发背景 随着现代中药的广泛应用&#xff0c;中药材的存储环境对其质量有着至关重要的影响。温湿度、烟雾、火灾等环境因素&#xff0c;若不加以控制&#xff0c;将会导致中药材失效或变质。因此&#xff0c;设计一个基于单片机的…

casaos安装最新版homeassistant-arm

进入cosOS界面点自定义安装 Docker镜像:homeassistant/armv7-homeassistant Tag:2024.12.2 标题&#xff1a;Home Assistant 图片路径&#xff1a;https://cdn.jsdelivr.net/gh/IceWhaleTech/CasaOS-AppStoremain/Apps/HomeAssistant/icon.png Web UI&#xff1a;http&…

Fabric环境部署-安装Go

安装go语言环境 国内镜像&#xff1a;Go下载 - Go语言中文网 - Golang中文社区 1.选择版本下载后解压&#xff1a;注意go1.11.linux-amd64.tar.gz换成你下的 sudo tar zxvf go1.21.linux-amd64.tar.gz -C /usr/local 2.. 创建Go目录 mkdir $HOME/go 3. 用vi打开~./bashrc&…

慧集通(DataLinkX)iPaaS集成平台-主数据映射管理(多系统间基础档案的映射)

主数据管理 主数据管理主要是解决不同业务系统之间历史数据不统一的问题&#xff0c;在该功能下主要分为三个模块分别为数据对象、应用系统、数据映射&#xff1b; 其中数据对象指的是我们的不同的对象&#xff0c;如&#xff1a;部门、人员、职级、科目、供应商等等&#xff…

Hoverfly 任意文件读取漏洞(CVE-2024-45388)

漏洞简介 Hoverfly 是一个为开发人员和测试人员提供的轻量级服务虚拟化/API模拟/API模拟工具。其 /api/v2/simulation​ 的 POST 处理程序允许用户从用户指定的文件内容中创建新的模拟视图。然而&#xff0c;这一功能可能被攻击者利用来读取 Hoverfly 服务器上的任意文件。尽管…

基于单片机的公交车报站系统设计

引言&#xff1a;单片机应用实践是电类相关专业一门必修的专业技术基础课&#xff0c;其教学目的就是为了使学生能深入了解模拟电路、数字电路、EDA 技术、传感器、单片机原理及其相关接口的综合应用技术&#xff0c;为此我们选了一个典型的实践题目- 公交车报站系统设计&#…

基于Java的超级玛丽游戏的设计与实现【源码+文档+部署讲解】

目 录 1、绪论 1.1背景以及现状 1.2 Java语言的特点 1.3 系统运行环境及开发软件&#xff1a; 1.4 可行性的分析 1.4.1 技术可行性 1.4.2 经济可行性 1.4.3 操作可行性 2、 需求分析 2.1 用户需求分析 2.2功能需求分析 2.3界面设计需求分析…

关于数组的一些应用--------数组作函数的返回值(斐波那契数列数列的实现)

数组在作为函数的返回值&#xff0c;一个很经典的例子就是获取斐波那契数列的前N项 代码思路&#xff1a; 设计思路 输入&#xff1a; 输入一个整数 n&#xff0c;表示要生成斐波那契数列的长度。 输出&#xff1a; 输出一个长度为 n 的整数数组&#xff0c;其中每个元素为斐…

灰度图的Stride和RGB的Stride有什么区别呢?

灰度图&#xff08;Grayscale&#xff09;和RGB图像的步长&#xff08;Stride&#xff09;计算确实有所不同&#xff0c;主要是因为它们每个像素占用的字节数不同。以下是两者的区别及对齐要求&#xff1a; 灰度图&#xff08;Grayscale&#xff09; 每个像素占用的字节数&…

使用WebSocket 获取实时数据

回车发送数据&#xff0c;模拟服务器发送数据 效果图&#xff1a; 源码&#xff1a; <template><div><h1>WebSocket 实时数据</h1><input type"text" v-model"ipt" keyup.enter"sendMessage(ipt)"><div v-if…