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

枚举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函数。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

科研绘图系列:R语言单细胞数据常见的可视化图形

禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据数据预处理图1图2图3图4图5图6系统信息参考介绍 单细胞数据常见的可视化图形 因为本教程是单细胞数据,因此运行本画图脚本需要电脑的内存最少32Gb 加载…

打造三甲医院人工智能矩阵新引擎(二):医学影像大模型篇--“火眼金睛”TransUNet

一、引言 1.1 研究背景与意义 在现代医疗领域,医学影像作为疾病诊断与治疗的关键依据,发挥着不可替代的作用。从传统的X射线、CT(计算机断层扫描)到MRI(磁共振成像)等先进技术,医学影像能够直观呈现人体内部结构,为医生提供丰富的诊断信息,涵盖疾病识别、病灶定位、…

IP查询于访问控制保护你我安全

IP地址查询 查询方法&#xff1a; 命令行工具&#xff1a; ①在Windows系统中&#xff0c;我们可以使用命令提示符&#xff08;WINR&#xff09;查询IP地址&#xff0c;在弹窗中输入“ipconfig”命令查看本地网络适配器的IP地址等配置信息&#xff1b; ②在Linux系统中&…

2025新春烟花代码(一)HTML5夜景放烟花绽放动画效果

标题预览效果 标题HTML代码 <!DOCTYPE html> <html lang"en"> <script>var _hmt _hmt || [];(function () {var hm document.createElement("script");hm.src "https://hm.baidu.com/hm.js?45f95f1bfde85c7777c3d1157e8c2d34&…

【Rust自学】10.6. 生命周期 Pt.2:生命周期的语法与例子

喜欢的话别忘了点赞、收藏加关注哦&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 10.6.1. 生命周期标注语法 生命周期的标注并不会改变引用的生命周期长度。如果某个函数它制定了泛型生命周期参数&#xff0c;那么它就可…

【C语言程序设计——选择结构程序设计】求一元二次方程的根(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 sqrt() 函数 编程要求 测试说明 通关代码 测试结果 任务描述 本关任务&#xff1a;根据求根公式&#xff0c;计算并输出一元二次方程的两个实根&#xff0c;要求精确道小数点后2位。要求方程系数从键盘输入。如果输入的系数不满足求…

【C++数据结构——图】图的邻接矩阵和邻接表的存储(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 1. 带权有向图 2. 图的邻接矩阵 3. 图的邻接表 测试说明 通关代码 测试结果 任务描述 本关任务&#xff1a;编写一个程序实现图的邻接矩阵和邻接表的存储。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a; 带权有向图…

java 转义 反斜杠 Unexpected internal error near index 1

代码&#xff1a; String str"a\\c"; //出现异常&#xff0c;Unexpected internal error near index 1 //System.out.println(str.replaceAll("\\", "c"));//以下三种都正确 System.out.println(str.replace(\\, c)); System.out.println(str.r…

QML学习(七) 学习QML时,用好Qt设计器,快速了解各个组件的属性

在初步学习QML时&#xff0c;特别建议看看Qt设计器&#xff0c;先利用Qt Quick设计师的使用&#xff0c;快速的对Qt Quick的各个组件及其常用的属性&#xff0c;有个初步的了解和认识。如果初始学习一上来直接以代码形式开干&#xff0c;很容易一头雾水。而设计器以最直白的所见…

Flutter 鸿蒙化 flutter和鸿蒙next混和渲染

前言导读 这一个节课我们讲一下PlatformView的是使用 我们在实战中有可能出现了在鸿蒙next只加载一部分Flutter的情况 我们今天就讲一下这种情况具体实现要使用到我们的PlatformView 效果图 具体实现: 一、Native侧 使用 DevEco Studio工具打开 platform_view_example\oho…

js逆向实战(1)-- 某☁️音乐下载

下载某云音乐源文件.mp4格式 首先随便点进一首歌&#xff0c;如图所示获取该音乐id&#xff0c;然后点击播放键&#xff0c;打开F12进行查询XHR 由此可知&#xff0c;实际请求网址是 https://music.163.com/weapi/song/enhance/player/url/v1?csrf_token「你的token」url需带…

学习随笔:word2vec在win11 vs2022下编译、测试运行

word2vec 官网word2vec的本质是在自然语言词条数据集与计算机浮点数据集之间建立双射关系。word2vec建立的数据集最厉害的一点是&#xff0c;将自然语言词条数据集内部的推理过程&#xff0c;映射到了计算机浮点数据集内部的数值运算。我个人感觉理解这个数据映射方式是理解AI大…

开源数据集成平台白皮书重磅发布《Apache SeaTunnel 2024用户案例合集》!

2025年新年临近&#xff0c;Apache SeaTunnel 社区用户案例精选&#x1f4d8;也跟大家见面啦&#xff01;在过去的时间里&#xff0c;SeaTunnel 社区持续成长&#xff0c;吸引了众多开发者的关注与支持。 为了致谢一路同行的伙伴&#xff0c;也为了激励更多人加入技术共创&…

Milvus×合邦电力:向量数据库如何提升15%电价预测精度

01. 全球能源市场化改革下的合邦电力 在全球能源转型和市场化改革的大背景下&#xff0c;电力交易市场正逐渐成为优化资源配置、提升系统效率的关键平台。电力交易通过市场化手段&#xff0c;促进了电力资源的有效分配&#xff0c;为电力行业的可持续发展提供了动力。 合邦电力…

Day21补代码随想录_20241231_669.修剪二叉搜索树|108.将有序数组转换为二叉搜索树|538.把二叉搜索树转换为累加树

669.修剪二叉搜索树 题目 【比增加和删除节点难的多】 给你二叉搜索树的根节点 root &#xff0c;同时给定最小边界 low 和最大边界 high。通过修剪二叉搜索树&#xff0c;使得所有节点的值在 [low, high]中。修剪树 不应该 改变保留在树中的元素的相对结构 (即&#xff0c;…

机场安全项目|基于改进 YOLOv8 的机场飞鸟实时目标检测方法

目录 论文信息 背景 摘要 YOLOv8模型结构 模型改进 FFC3 模块 CSPPF 模块 数据集增强策略 实验结果 消融实验 对比实验 结论 论文信息 《科学技术与工程》2024年第24卷第32期刊载了中国民用航空飞行学院空中交通管理学院孔建国, 张向伟, 赵志伟, 梁海军的论文——…

【USRP】教程:在Macos M1(Apple芯片)上安装UHD驱动(最正确的安装方法)

Apple芯片 前言安装Homebrew安装uhd安装gnuradio使用b200mini安装好的路径下载固件后续启动频谱仪功能启动 gnu radio关于博主 前言 请参考本文进行安装&#xff0c;好多人买了Apple芯片的电脑&#xff0c;这种情况下&#xff0c;可以使用UHD吗&#xff1f;答案是肯定的&#…

【C++数据结构——内排序】希尔排序(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 1. 排序算法基础概念 2.插入排序知识 3. 间隔序列&#xff08;增量序列&#xff09;的概念 4. 算法的时间复杂度和空间复杂度分析 5. 代码实现技巧&#xff08;如循环嵌套、索引计算&#xff09; 测试说明 我的通关代码: 测试结…

每天看一个Fortran文件(9)

最后的输出变量是f 这里面调用了一个关键的子程序&#xff0c;spectral_nudging_filter_fft_2d_ncar 这是一个谱逼近的二维快速傅里叶变换过滤的程序。 二维的滤波这个还不是很清楚&#xff0c;找找技术文件看下 超详细易懂FFT&#xff08;快速傅里叶变换&#xff09;及代码…

Centos源码安装MariaDB 基于GTID主从部署(一遍过)

MariaDB安装 安装依赖 yum install cmake ncurses ncurses-devel bison 下载源码 // 下载源码 wget https://downloads.mariadb.org/interstitial/mariadb-10.6.20/source/mariadb-10.6.20.tar.gz // 解压源码 tar xzvf mariadb-10.5.9.tar.gz 编译安装 cmake -DCMAKE_INSTA…