【Rust自学】9.2. Result枚举与可恢复的错误 Pt.1:match、expect和unwrap处理错误

喜欢的话别忘了点赞、收藏加关注哦,对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=・ω・=)

9.2.1. Result枚举

通常情况下,错误都没有严重到需要停止整个程序的地步。某个函数之所以运行失败或者是遇到错误通常是由一些可以简单解释并做出响应的原因引起的。比如说程序要打开某个文件,但是这个文件并不存在,这个时候通常会考虑创建这个文件而不是直接终止程序。

Rust提供了Result这个枚举类型来处理这种可能失败的情况。它的定义是:

enum Result<T, E> {
	OK(T),
	Err(E),
}

它有两个泛型的类型参数,一个是T一个是E,它有两个变体,每个都关联了数据,OK关联了T,Err关联了E。泛型在第十章会讨论,现在只需要知道T是操作成功的情况下,OK变体里返回的数据的类型;E是在操作失败的情况下,Err变体里返回的错误的类型。

看个例子:

use std::fs::File;  
fn main() {  
    let f = File::open("6657.txt");  
}

这个代码的操作是打开文件,但这个文件不一定存在,所以说函数的运行可能会失败,所以File::open这个函数的返回值是Result枚举。这个Result里面第一个参数是std::fs::File,也就是文件类型(成功的时候返回);而第二个是std::io::Error,也就是io错误(失败的时候返回)

9.2.2. 用match处理Result

Option枚举一样,Result及其变体也是由预导入模块(prelude)带入作用域的,在写代码时不需要额外的引入。如下例:

use std::fs::File;  
fn main() {  
    let f = File::open("6657.txt");  
    let f = match f {  
        Ok(file) => file,  
        Err(e) => panic!("Error: {}", e),  
    };  
}

如果返回的值是Ok,那么就把它所关联的值绑定到file上再返回回去赋给f;如果返回的值是Err,那么就把错误信息绑定在e上由panic!宏打印出来并停止程序。

9.2.3. 匹配不同的错误

我们把上面的例子完善一下,如果出现找不到的情况,就创建这个文件,如果连创建都不成功或者是出现了除了找不到意外的情况(比如没有权限打开),才触发panic!

use std::fs::File;  
use std::io::ErrorKind;  
  
fn main() {  
    let f = File::open("6657.txt");  
    let f = match f {  
        Ok(file) => file,  
        Err(e) => match e.kind() {  
            ErrorKind::NotFound => match File::create("6657.txt") {  
                Ok(fc) => fc,  
                Err(e) => panic!("Problem creating file: {:?}", e),  
            },  
            other_error => panic!("Problem opening file: {:?}", other_error),  
        },  
    };  
}
  • 在最外层仍然是如果f的值是Ok就把文件内容返回给f
  • 但在处理Err变体时有不同,Err所附带的数据的类型是std::io::Error,这个struct上有一个.kind()方法,通过这个方法可以获得std::io::ErrorKind这个类型值,它也是一个枚举,也是由标准库提供的,它里面的变体是用来描述io操作可能引起的不同错误
  • ErrorKind里面有一个变体ErrorKind::NotFound,表示文件不存在,这个时候就应该创建文件,在下面我们再讨论创建文件。除了ErrorKind::NotFound,也可能有其他错误(比如说没有权限读取),这里把其他错误赋给了other_error这个值,并由panic!打印出来然后停止程序。
  • 对于创建文件,可以使用File::create()这个函数,其参数就是文件名。而创建文件本身也有可能会失败(比如没权限),所以File::create()的返回值也是Result类型,那就再用一个match表达式来处理,如果是OK(创建成功),那就把OK关联的值,也就是这个新创建的文件呢的内容(内容肯定是空的,因为是新创建的)绑定在fc这个变量上返回赋给f;如果是Err(创建失败),就把Err所关联的错误信息绑定在e上用panic!打印出来并停止程序。

match确实用的比较多,但也比较原始,这里的套娃是其可读性大大降低(虽然对比其他语言可能可读性还要高一些)。而在第13章会讲一个概念叫做闭包(closure),Result类型有很多方法接受闭包作为参数,而且这些方法都是使用match实现的,能够使得代码更加简洁,我把使用闭包的代码例写在这里,但现在不会讲,到13章才会讲。

use std::fs::File;
use std::io::ErrorKind;

fn main() {
    let greeting_file = File::open("6657.txt").unwrap_or_else(|error| {
        if error.kind() == ErrorKind::NotFound {
            File::create("6657.txt").unwrap_or_else(|error| {
                panic!("Problem creating the file: {error:?}");
            })
        } else {
            panic!("Problem opening the file: {error:?}");
        }
    });
}

9.2.4. unwrap方法

match表达式确实灵活有用,但写出来的代码也确实复杂了一些,而Result这个枚举类型本身也定义了许多的辅助方法来应对各式各样的任务,其中有一个常用的方法叫unwrap

如果unwrap接收到了OK,那么它就会把OK附带的值返回;而如果接收到了Err,那么unwrap就会调用panic!宏。比如说用unwrap重写9.2.2中的代码:

use std::fs::File;  
  
fn main() {  
    let f = File::open("6657.txt").unwrap();  
}

unwrap就相当于match表达式的快捷方法。它的缺点就是错误信息不可以自定义。

9.2.5. expect方法

那如果我想要unwrap的快捷性,又想要自定义错误信息怎么办?针对这种情况,Rust提供了expect方法,如果你有印象的话,在第一章的猜数游戏中就用过这种方法。

试试用expect重写unwrap的代码例:

use std::fs::File;  
  
fn main() {  
    let f = File::open("6657.txt").expect("file not found");  
}

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

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

相关文章

lec7-路由与路由器

lec7-路由与路由器 1. 路由器硬件 路由器的硬件部分&#xff1a; 断电失去&#xff1a; RAM断电不失去&#xff1a;NVRAM&#xff0c; Flash&#xff0c; ROMinterface也算是一部分 路由器是特殊组件的计算机 console 口进行具体的调试 辅助口&#xff08;Auxiliary&…

spring防止重复点击,两种注解实现(AOP)

第一种&#xff1a;EasyLock 简介 为了简化可复用注解&#xff0c;自己实现的注解&#xff0c;代码简单随拿随用 使用方式 1.创建一个注解 Target(ElementType.METHOD) Retention(RetentionPolicy.RUNTIME) Documented public interface EasyLock {long waitTime() default …

Linux-Ubuntu之I2C通信

Linux-Ubuntu之I2C通信 一&#xff0c;I2C通信原理1.写时序2.读时序 二&#xff0c;代码实现三&#xff0c;显示 一&#xff0c;I2C通信原理 使用I2C接口驱动AP3216C传感器&#xff0c;该传感器能实现两个效果&#xff0c;一个是感应光强&#xff0c;另一个是探测物体与传感器…

音视频入门基础:MPEG2-PS专题(4)——FFmpeg源码中,判断某文件是否为PS文件的实现

一、引言 通过FFmpeg命令&#xff1a; ./ffmpeg -i XXX.ps 可以判断出某个文件是否为PS文件&#xff1a; 所以FFmpeg是怎样判断出某个文件是否为PS文件呢&#xff1f;它内部其实是通过mpegps_probe函数来判断的。从《FFmpeg源码&#xff1a;av_probe_input_format3函数和AVI…

框架模块说明 #09 日志模块_01

背景 日志模块是系统的重要组成部分&#xff0c;主要负责记录系统运行状态和定位错误问题的功能。通常&#xff0c;日志分为系统日志、操作日志和安全日志三类。虽然分布式数据平台是当前微服务架构中的重要部分&#xff0c;但本文的重点并不在此&#xff0c;而是聚焦于自定义…

【数据仓库】hadoop3.3.6 安装配置

文章目录 概述下载解压安装伪分布式模式配置hdfs配置hadoop-env.shssh免密登录模式设置初始化HDFS启动hdfs配置yarn启动yarn 概述 该文档是基于hadoop3.2.2版本升级到hadoop3.3.6版本&#xff0c;所以有些配置&#xff0c;是可以不用做的&#xff0c;下面仅记录新增操作&#…

算法题(25):只出现一次的数字(三)

审题&#xff1a; 该题中有两个元素只出现一次并且其他元素都出现两次&#xff0c;需要返回这两个只出现一次的数&#xff0c;并且不要求返回顺序 思路: 由于对空间复杂度有要求&#xff0c;我们这里不考虑哈希表。我们采用位运算的方法解题 方法&#xff1a;位运算 首先&#…

将机器学习预测模型融入AI agent的尝试(一)

将机器学习临床预测模型融入AI agent的尝试&#xff08;一&#xff09; 我主要是使用机器学习制作临床预测模型和相关的应用&#xff0c;最近考虑的事情是自己之前的的工作能不能和AI agent进行融合&#xff0c;将AI 对自然语言理解能力和预测模型的预测能力结合在一起&#x…

51单片机——按键实验

由于机械点的弹性作用&#xff0c;按键开关在闭合时不会马上稳定的接通&#xff0c;在断开时也不会一下子断开&#xff0c;因而在闭合和断开的瞬间均伴随着一连串的抖动。抖动时间的长短由按键的机械特性决定的&#xff0c;一般为 5ms 到 10ms&#xff0c;为了确保 CPU 对按键的…

电子邮件对网络安全的需求

&#xff08; 1&#xff09;机密性&#xff1a;传输过程中不被第三方阅读到邮件内容&#xff0c;只有真正的接收方才可以阅读邮件。&#xff08; 1.5 分&#xff09; &#xff08; 2&#xff09;完整性&#xff1a;支持在邮件传输过程中不被篡改&#xff0c;若发生篡改&#…

vue路由模式面试题

vue路由模式 1.路由的模式有哪些?有什么区别? history和hash模式 区别: 1.表现的形态不同: 在地址栏url中:hash模式中带有**#**号,history没有 2.请求错误时表现不同: 在hash模式中,对于404地址请求时,不会进行请求 但是在history模式中,对于404请求时,仍然会进行请求…

电子应用设计方案86:智能 AI背景墙系统设计

智能 AI 背景墙系统设计 一、引言 智能 AI 背景墙系统旨在为用户创造一个动态、个性化且具有交互性的空间装饰体验&#xff0c;通过融合先进的技术和创意设计&#xff0c;提升室内环境的美观度和功能性。 二、系统概述 1. 系统目标 - 提供多种主题和风格的背景墙显示效果&…

Python爬虫 - 豆瓣图书数据爬取、处理与存储

文章目录 前言一、使用版本二、需求分析1. 分析要爬取的内容1.1 分析要爬取的单个图书信息1.2 爬取步骤1.2.1 爬取豆瓣图书标签分类页面1.2.2 爬取分类页面1.2.3 爬取单个图书页面 1.3 内容所在的标签定位 2. 数据用途2.1 基础分析2.2 高级分析 3. 应对反爬机制的策略3.1 使用 …

西安电子科技大学初/复试笔试、面试、机试成绩占比

西安电子科技大学初/复试笔试、面试、机试成绩占比 01通信工程学院 02电子工程学院 03计算机科学与技术学院 04机电工程学院 06经济与管理学院 07数学与统计学院 08人文学院 09外国语学院 12生命科学与技术学院 13空间科学与技术学院 14先进材料与纳米科技学院 15网络与信息安…

多模态论文笔记——CogVLM和CogVLM2(副)

大家好&#xff0c;这里是好评笔记&#xff0c;公主号&#xff1a;Goodnote&#xff0c;专栏文章私信限时Free。本文详细介绍多模态模型的LoRA版本——CogVLM和CogVLM2。在SD 3中使用其作为captioner基准模型的原因和优势。 文章目录 CogVLM论文背景VLMs 的任务与挑战现有方法及…

智慧工地信息管理与智能预警平台

建设背景与政策导向 智慧工地信息管理与智能预警平台的出现&#xff0c;源于工地管理面临的诸多挑战&#xff0c;如施工地点分散、危险区域多、监控手段落后等。随着政府对建筑产业现代化的积极推动&#xff0c;各地纷纷出台政策支持智慧工地的发展&#xff0c;旨在通过信息技…

【从零开始入门unity游戏开发之——C#篇42】C#补充知识——随机数(Random)、多种方法实现string字符串拼接、语句的简写

文章目录 一、随机数1、Random.Next()生成随机整数示例&#xff1a;生成一个随机整数生成指定范围内的随机整数 2、Random.NextSingle生成随机浮点数示例&#xff1a;生成随机浮点数 3、 生成随机字母或字符示例&#xff1a;生成随机字母示例&#xff1a;生成随机小写字母 二、…

「Mac畅玩鸿蒙与硬件54」UI互动应用篇31 - 滑动解锁屏幕功能

本篇教程将实现滑动解锁屏幕功能&#xff0c;通过 Slider 组件实现滑动操作&#xff0c;学习事件监听、状态更新和交互逻辑的实现方法。 关键词 滑动解锁UI交互状态管理动态更新事件监听 一、功能说明 滑动解锁屏幕功能包含以下功能&#xff1a; 滑动解锁区域&#xff1a;用…

VScode SSH 错误:Got bad result from install script 解決

之前vscode好好的&#xff0c;某天突然连接报错如下 尝试1. 服务器没有断开,ssh可以正常连接 2. 用管理员权限运行vscode&#xff0c;无效 3. 删除服务器上的~/.vscode-server 文件夹&#xff0c;无效 试过很多后&#xff0c;原来很可能是前一天anaconda卸载导致注册表项 步…

[论文笔记]Representation Learning with Contrastive Predictive Coding

引言 今天带来论文 Representation Learning with Contrastive Predictive Coding的笔记。 提出了一种通用的无监督学习方法从高维数据中提取有用表示&#xff0c;称为对比预测编码(Contrastive Predictive Coding,CPC)。使用了一种概率对比损失&#xff0c; 通过使用负采样使…