Rust之错误处理
在Rust中,将错误分为两种,可恢复错误和不可恢复错误。所谓可恢复错误就是指类似于文件未找到这类错误,一般需要将它们报告给用户并再次尝试进行操作,而不可恢复错误往往就是Bug,需要停止程序的运行。
1、不可恢复错误与panic!:
当代码中出现没有预料到的错误时,Rust提供了一个特殊的宏panoc!,程序会在panic!宏执行时打印一段错误提示信息,展开并清理当前的调用栈,然后退出程序的执行。
当panic发生时,程序会默认开始栈展开。这意味着Rust会沿着调用栈的反向顺序遍历所有调用函数,并依次清理这些函数中的数据。但是为了支持这种遍历和清理操作,我们需要在二进制中存储许多额外信息。
2、可恢复错误与Result:
在程序的调试中,有些错误没有严重到需要停止整个程序的运行,例如尝试打开一个文件,而文件不存在的情况。这种情况可以使用Result类型来处理。在Result枚举中,定义了两个变体——OK和Err。示例:
enum Result<T,E>{OK(T),Err(E),
}
这里的T和E都是泛型,T代表了OK变体中包含的值的类型,该变体中的值会在执行成功时返回;E代表了Err变体中包含的错误类型,该变体会在执行失败时返回。
(1)、匹配不同的错误:
由于在编程时,会遇到不同的错误,那么就可以根据错误的种类来执行不同的操作。示例:
use std::fs::File;
use std::io::ErrorKind;
fn main() {let f = File::open("hello.txt");let f = match f {Ok(file) => file,Err(error) => match error.kind() {ErrorKind::NotFound => match File::create("hello.txt") {Ok(fc) => fc,Err(e) => panic!("Tried to create file but there was a problem:{:?}", e),},other_error => panic!("There was a problem opening the file: {:?}",other_error),},};
}
File::open返回的Err变体中的错误值类型,是定义在某个标准库中的结构体类型:io::Error。这个结构体拥有一个被称作kind的方法,可以通过调用它来获得 io::ErrorKind 值。这个io::ErrorKind枚举是由标准库提供的,它的变体被用于描述io操作所可能导致的不同错误。这里使用的变体是ErrorKind::NotFound,它用于说明我们尝试打开的文件不存在。所以,我们不但对变量f使用了match表达式,还在内部对error.kind()使用了match表达式。
(2)、失败时触发panic的快捷方式:unwrap和expect:
虽然使用match运行得很不错,但使用它所编写出来的代码可能会显得有些冗长,且无法较好地表明其意图。类型Result<T, E>本身也定义了许多辅助方法来应对各式各样的任务。当Result的返回值是Ok变体时,unwrap就会返回Ok内部的值。而当Result的返回值是Err变体时,unwrap则会替我们调用panic! 宏。示例:
use std::fs::File;
fn main() {let f = File::open("hello.txt").unwrap();
}
还有另外一个被称作expect的方法,它允许我们在unwrap的基础上指定panic! 所附带的错误提示信息。使用expect并附带上一段清晰的错误提示信息可以阐明你的意图,并使你更容易追踪到panic的起源。示例:
use std::fs::File;
fn main() {let f = File::open("hello.txt").expect("Failed to open hello.txt");
}
使用expect所实现的功能与unwrap完全一样:要么返回指定文件句柄,要么触发panic! 宏调用。唯一的区别在于,expect触发panic! 时会将传入的参数字符串作为错误提示信息输出,而unwrap触发的panic! 则只会携带一段简短的默认信息。
(3)、传播错误:
编写的函数中包含了一些可能会执行失败的调用时,除了可以在函数中处理这个错误,还可以将这个错误返回给调用者,让他们决定应该如何做进一步处理。这个过程也被称作传播错误,在调用代码时它给了用户更多的控制能力。与编写代码时的上下文环境相比,调用者可能会拥有更多的信息和逻辑来决定应该如何处理错误。
传播错误的模式在Rust编程中非常常见,所以Rust专门提供了一个问号运算符(?)来简化它的语法。示例:
use std::io;
use std::io::Read;
use std::fs::File;
fn read_username_from_file() -> Result<String, io::Error> {let mut f = File::open("hello.txt")?;let mut s = String::new();f.read_to_string(&mut s)?;Ok(s)
}
通过将?放置于Result值之后,我们实现了与使用match表达式来处理Result时一样的功能。假如这个Result的值是Ok,那么包含在Ok中的值就会作为这个表达式的结果返回并继续执行程序。假如值是Err,那么这个值就会作为整个程序的结果返回,如同使用了return一样将错误传播给调用者。
match表达式与?运算符的一个区别:被?运算符所接收的错误值会隐式地被from函数处理,这个函数定义于标准库的From trait中,用于在错误类型之间进行转换。当?运算符调用from函数时,它就开始尝试将传入的错误类型转换为当前函数的返回错误类型。当一个函数拥有不同的失败原因,却使用了统一的错误返回类型来同时进行表达时,这个功能会十分有用。只要每个错误类型都实现了转换为返回错误类型的from函数,?运算符就会自动处理所有的转换过程。
注:?运算符只能被用于返回Result的函数。
3、要不要使用panic!:
什么时候应该使用panic!,而什么时候又应该返回Result呢?代码一旦发生panic,就再也没有恢复的可能了。只要你认为自己可以代替调用者决定某种情形是不可恢复的,那么就可以使用panic!,而不用考虑错误是否存在可以恢复的机会。当你选择返回一个Result值时,你就将这种选择权交给了调用者。调用者可以根据自己的实际情况来决定是否要尝试进行恢复,或者干脆认为Err是不可恢复的,并使用panic! 来将可恢复错误转变为不可恢复错误。因此,我们会在定义一个可能失败的函数时优先考虑使用Result方案。
相关文章:
Rust之错误处理
在Rust中,将错误分为两种,可恢复错误和不可恢复错误。所谓可恢复错误就是指类似于文件未找到这类错误,一般需要将它们报告给用户并再次尝试进行操作,而不可恢复错误往往就是Bug,需要停止程序的运行。 1、不可恢复错误…...
docker compose快速编排
Docker-compose概述 Docker-Compose项目是Docker官方的开源项目,负责实现对Docker容集群的快速编排 Docker-Compose将所管理的容器分为三层,分别是工程(project),服务(service)以及容器&#x…...
java.io.File类的使用
文章目录 概述构造器常用方法1、获取文件和目录基本信息2、列出目录的下一级3.File类的重命名功能4、判断功能的方法5、创建、删除功能 练习 概述 File类及本章下的各种流,都定义在java.io包下。一个File对象代表硬盘或网络中可能存在的一个文件或者文件目录&#…...
TypeScript技能总结(三)
typescript是js的超集,目前很多前端框架都开始使用它来作为项目的维护管理的工具,还在不断地更新,添加新功能中,我们学习它,才能更好的在的项目中运用它,发挥它的最大功效 //泛型 > 参数和返回值类型相…...
python绿色版运行程序,python 绿色版免安装
大家好,小编来为大家解答以下问题,python绿色版运行程序,python 绿色版免安装,今天让我们一起来看看吧! 软件简介 Python3.7.0 是一种被广大从业者广泛使用的通用型设计语言。该软件提供了丰富全面的模块,并…...
Python 向Excel写数据
1.项目终端导入 xlwt 库 pip install xlwt2.导入依赖包 import xlwt3.创建Excel表格类型文件 调用xlwt模块中的Workbook方法来创建一个excel表格类型文件,其中的第一个参数是设置数据的编码格式,这里是’utf-8’的形式,style_compression设…...
MySQL(1)
MySQL创建数据库和创建数据表 创建数据库 1. 连接 MySQL mysql -u root -p 2. 查看当前的数据库 show databases; 3. 创建数据库 create database 数据库名; 创建数据库 4. 创建数据库时设置字符编码 create database 数据库名 character set utf8; 5. 查看和显示…...
Android10 Recovery系列(二)增加OTG升级功能
一 、背景 起因是遇到了客户有这个需求,本着了解的原则,去看了一下之前Android版本的代码,想看看之前有没有现成的实现,移植过来。结果很不幸,没有找到。于是自己开始了功能实现的过程。下面分享一下该功能的实现 二 、准备工作 首先简单了解一下Recovery 模块的系统升…...
el-popover使用自定义图标
使用el-popover实现鼠标点击或浮动到自定义图标上弹出表格弹窗,官方文档上使用的是按钮el-button,如果想换成图标或其他的组件的话直接把el-button替换掉即可。注意替换之后的组件一定要加slot“reference”,不然组件是显示不出来的。 代码如…...
KCOM4串口转键鼠控制线测试说明
1.KOCM4介绍 KCOM4是一款最新开发的串口转键盘鼠标控制线,采用32位内核,最大60Mhz的工作频率,完美适用于游戏挂机等应用场景(如果是用在工作电脑控制或展厅电脑控制推荐CH9329双头线)。KCOM4支持普通键盘、相对鼠标、…...
2023华数杯数学建模C题完整5问代码思路分析
目前已经写出2023华数杯C题母亲身心健康对婴儿成长的影响全部5问的完整代码和42页论文(正文30页,论文部分摘要如下: 本文共解决了五个问题,涉及婴儿行为特征、睡眠质量与母亲的身体指标和心理指标的关系,以及如何优化…...
02_kafka_基本概念_基础架构
文章目录 常见的消息队列工作模式基本概念kafka 特性Kafka 基本架构topic 分区的 目的/ 好处 日志存储形式消费者,消费方式 逻辑消费组 高性能写入: 顺序写 mmap读取:零拷贝DMA 使用场景 常见的消息队列工作模式 至多一次:消息被…...
HTTP 常用状态码 301 302 304 403
HTTP 常用状态码 301 302 304 403 301 永久重定向,浏览器会把重定向后的地址缓存起来,将来用户再次访问原始地址时,直接引导用户访问新地址 302 临时重定向,浏览器会引导用户进入新地址,但不会缓存原始地址,…...
分布式 - 服务器Nginx:一小时入门系列之静态网页配置
文章目录 1. 静态文件配置2. nginx listen 命令解析3. nginx server_name 命令解析4. nginx server 端口重复5. nginx location 命令 1. 静态文件配置 在 /home 文件下配置一个静态的AdminLTE后台管理系统: [rootnginx-dev conf.d]# cd /home [rootnginx-dev home…...
kubernetes网络之网络策略-----Network Policies - Example
创建一个Deployment并配置Service 创建一个 nginx Deployment 用于演示 Kubernetes 的 NetworkPolicy: kubectl create deployment nginx --imagenginx 输出结果 deployment.apps/nginx created通过Service暴露该Deployment kubectl expose deployment nginx --po…...
【GDI/GDI+】如何抓取屏幕保存到bitmap文件?
问题 如何抓取屏幕保存到bitmap文件? 方法 GDI 方法 1、抓取。 HBITMAP CRectChartUI::GetBitmap(HDC hDC) {HDC hMemDC;int x, y;int nWidth, nHeight;HBITMAP hBitmap, hOldBitmap;hMemDC CreateCompatibleDC(hDC);nWidth GetDeviceCaps(hDC, HORZRES);nHei…...
HDFS介绍
目录 编辑 一、HDFS基础 1.1 概述 1.2 HDFS的设计目标 1.2.1 硬件故障 1.2.2 流式数据访问 1.2.3 超大数据集 1.2.4 简单的一致性模型 1.2.5 移动计算而不是移动数据 1.2.6 跨异构硬件和软件平台的可移植性 1.3 基础概念 1.3.1 块(Block) 1.3.2 复制…...
每日一题——两数之和
题目 给出一个整型数组 numbers 和一个目标值 target,请在数组中找出两个加起来等于目标值的数的下标,返回的下标按升序排列。 (注:返回的数组下标从1开始算起,保证target一定可以由数组里面2个数字相加得到࿰…...
Maven: ‘mvn‘ is not recognized as an internal or external command
下载并配置好Maven之后,CMD测试安装是否成功:mvn -v 提示: mvn is not recognized as an internal or external command, operable program or batch file. 检查环境变量: MAVEN_HOME: %MAVEN_HOME%\bin: 看上去没问题&#x…...
CubeSLAM: Monocular 3D Object SLAM——论文简述
一、简介 提出一种在动态和静态环境中同时进行3D目标检测和定位建图的方法,并且能够互相提升准确度。具体地,对于3D目标,其位置、方向和尺寸通过slam进行了优化;而3D目标作为slam中的路标,可以提供额外的语义和几何约…...
C++_核心编程_多态案例二-制作饮品
#include <iostream> #include <string> using namespace std;/*制作饮品的大致流程为:煮水 - 冲泡 - 倒入杯中 - 加入辅料 利用多态技术实现本案例,提供抽象制作饮品基类,提供子类制作咖啡和茶叶*//*基类*/ class AbstractDr…...
Xshell远程连接Kali(默认 | 私钥)Note版
前言:xshell远程连接,私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
自然语言处理——Transformer
自然语言处理——Transformer 自注意力机制多头注意力机制Transformer 虽然循环神经网络可以对具有序列特性的数据非常有效,它能挖掘数据中的时序信息以及语义信息,但是它有一个很大的缺陷——很难并行化。 我们可以考虑用CNN来替代RNN,但是…...
均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...
Python竞赛环境搭建全攻略
Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型(算法、数据分析、机器学习等)不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...
