30天拿下Rust之错误处理

概述

        在软件开发领域,对错误的妥善处理是保证程序稳定性和健壮性的重要环节。Rust作为一种系统级编程语言,以其对内存安全和所有权的独特设计而著称,其错误处理机制同样体现了Rust的严谨与实用。在Rust中,错误处理通常分为两大类:不可恢复的错误和可恢复的错误。这两种错误的处理方式在Rust的设计哲学中扮演着不同的角色,并且适用于不同的场景。

不可恢复的错误

        不可恢复的错误是指那些由于严重问题,导致程序无法继续执行的情况。这类错误通常是由于编程错误、资源耗尽、或者外部系统问题导致的。在Rust中,不可恢复的错误通过panic!宏来触发。

        当panic!被调用时,程序会立即停止当前的执行流程,并打印出一条错误消息,然后退出程序。因为panic!会导致程序崩溃,所以它通常只在开发过程中用于检测那些不应该发生的严重错误。

        在下面的示例代码中,如果除数b为0,会通过panic!宏来触发不可恢复的错误,并打印错误消息“Division by zero”。panic!被调用后,程序会立即终止,因此,后面的println!不会执行。

fn divide(a: i32, b: i32) -> i32 {if b == 0 {panic!("Division by zero");}a / b
}fn main() {let value = divide(66, 0);println!("{}", value);
}

        注意:在生产代码中,应当尽量避免使用panic!,因为它会导致程序不稳定和不可靠。相反,应该使用下面介绍的可恢复的错误机制来优雅地处理可能出现的错误,并确保程序在遇到问题时,能够以一种可预测和可控的方式做出响应。

可恢复的错误

        可恢复的错误是指那些可以通过某种方式修正或处理的错误,通常不会导致程序完全崩溃。在Rust中,这类错误通常通过Result枚举类型来表示。Result有两个可能的变体:Ok用于表示操作成功的结果,而Err用于表示错误。

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

        使用Result枚举类型,函数可以显式地表示它们可能失败,并返回一个错误值。调用这些函数的代码,可以选择如何处理这些错误,比如:重试、提供默认值、或者将错误传递给上层调用者。这种错误处理机制允许程序在发生错误时保持运行,并可能从错误中恢复。

        在下面的示例代码中,我们调用File::open方法尝试打开名为“CSDN.txt”的文件。这个方法返回一个Result类型,其中Ok变体包含文件句柄(如果文件打开成功),而Err变体包含错误信息(如果文件打开失败)。

use std::fs::File;fn main() {let file_handle = File::open("CSDN.txt");match file_handle {Ok(file) => {println!("open successfully");},Err(err) => {println!("failed: {}", err);}}
}

        如果想将一个可恢复的错误按照不可恢复的错误处理,Result类提供了两个方法:unwrap()和expect()。这两个方法是用于处理Result或Option类型的便捷方法,用于从这些类型中提取出内部值,但当值不存在(对于Option)或是一个错误状态(对于Result)时,都会导致程序panic。如果Option是None或者Result是Err(E),则unwrap()会触发panic,并打印出默认的panic!消息。expect()方法与unwrap()方法类似,但它允许我们自定义在panic时输出的错误消息。

fn main() {let opt_value: Option<i32> = Some(66);let value = opt_value.unwrap();println!("{}", value);let result: Result<i32, String> = Err("not valid".to_string());result.expect("failed");
}

        注意:在非生产环境或者确定不会出现错误的情况下可以使用unwrap()方法和expect()方法,但在实际项目开发中应尽量避免。

?运算符

        Rust提供了一个便捷的?运算符,用于简洁地传播错误。当Result类型变量出现在?后面时,如果它是Ok值,则解包其内部的值;如果是Err值,则从当前函数返回该错误。

        在下面的示例代码中,?操作符用于简化错误处理。如果在其前面的操作File::open和read_to_string返回Err变体,则整个表达式会立即返回该错误。这使得代码更加简洁,但也可能隐藏一些复杂的错误处理逻辑。在需要更精细控制错误处理的情况下,应该使用完整的match表达式或if let语句。

use std::fs::File;
use std::io::Read;fn read_file(filename: &str) -> Result<String, std::io::Error> {let mut file = File::open(filename)?;let mut contents = String::new();file.read_to_string(&mut contents)?;Ok(contents)
}fn main() {let result = read_file("CSDN.txt");match result {Ok(contents) => println!("content is: {}", contents),Err(e) => {println!("read file failed: {}", e);}}
}

自定义错误

        在Rust中,可以通过实现std::error::Error trait来创建自定义错误类型。这允许我们定义自己的错误类型,并能够更具体地描述程序中可能发生的错误情况。

        自定义错误类型通常包含一个或多个字段,这些字段可以包含有关错误的额外信息。通过实现Error trait,我们可以控制错误消息的格式,并且错误类型可以与其他期望Error trait的Rust错误处理机制一起工作。

        在下面的示例代码中,MyCustomError是一个简单的结构体,它包含一个描述错误的String字段。我们实现了Error trait,使得MyCustomError可以作为错误类型被使用。此外,我们还实现了fmt::Display trait,以定义错误打印时应该显示的字符串。process函数模拟了一些可能失败的操作,并在失败时返回一个MyCustomError实例。在main函数中,我们调用process函数并处理其返回的结果,并打印输出相应的信息。

use std::error::Error;
use std::fmt;// 自定义错误类型
#[derive(Debug)]
struct MyCustomError {desc: String,
}  // 实现Error trait
impl Error for MyCustomError {}// 实现Display trait
impl fmt::Display for MyCustomError {fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {write!(f, "{}", self.desc)}
}fn process() -> Result<(), MyCustomError> {Err(MyCustomError {desc: "something is wrong".to_string(),})
}fn main() {match process() {Ok(()) => println!("success"),Err(e) => {println!("failed: {}", e);}  }
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

词令微信小程序怎么添加到我的小程序?

微信小程序怎么添加到我的小程序&#xff1f; 1、找到并打开要添加的小程序&#xff1b; 2、打开小程序后&#xff0c;点击右上角的「…」 3、点击后底部弹窗更多选项&#xff0c;请找到并点击「添加到我的小程序」&#xff1b; 4、添加成功后&#xff0c;就可以在首页下拉我的…

迈入编程世界:C 语言初体验

写在前面&#xff1a;OK啊&#xff0c;前面我们介绍了C语言开发环境的搭建&#xff0c;今天我们再来初步的认识一下C语言&#xff0c;了解C语言的基础框架、数据的表现形式以及输入和输出。 文章特点&#xff1a;不会很正经&#xff0c;不会很学术&#xff0c;不会很理论&#…

J4G企业通讯ip电话 sip对讲主机 停车场对讲主机

J4G企业通讯ip电话 sip对讲主机 停车场对讲主机 SV-J4G 是一款企业级彩屏网络电话&#xff0c;具有高清语音&#xff0c;320x240 2.8英寸彩屏&#xff0c;支持千兆以太网&#xff0c;12个SIP账号&#xff0c;支持PoE供电&#xff0c;支持外接EHS无线耳机&#xff0c;三方电话会…

C++有关内存的那些事

个人主页&#xff1a;PingdiGuo_guo 收录转栏&#xff1a;C干货专栏 前言 本篇博客是讲解关于C内存的一些知识点的。 文章目录 前言 1.内存函数 1.1memcpy函数 1.2memmove函数 1.3 memset函数 2.各数据类型占用 2.1bool类型 2.2char类型 2.3short、int、long类型及整数…

京东商品信息采集API商品价格商品详情图主图抓取接口key(提供测试入口)

item_get 获得JD商品详情item_search 按关键字搜索商品item_search_img 按图搜索京东商品&#xff08;拍立淘&#xff09;item_search_shop 获得店铺的所有商品item_history_price 获取商品历史价格信息item_recommend 获取推荐商品列表buyer_order_list 获取购买到的商品订单列…

CMake笔记之GLOB和GLOB_RECURSE的使用方法

CMake笔记之GLOB和GLOB_RECURSE的使用方法 —— 杭州 2024-03-19 夜 文章目录 CMake笔记之GLOB和GLOB_RECURSE的使用方法1.GLOB使用方法2.GLOB对比GLOB_RECURSE 1.GLOB使用方法 在 CMake 中&#xff0c;file(GLOB ...) 命令用于将匹配特定模式的文件列表赋值给变量。这可以用…

MySQL中replace into详解、批量更新、不存在插入存在则更新、replace into的坑

文章目录 一、replace into原理二、replace into的三种形式三、replace into 使用案例3.1、replace into values3.1.1、只有主键且主键冲突3.1.2、有主键有唯一索引且主键冲突3.1.3、有主键有唯一索引且唯一索引冲突(有坑)3.1.4、有主键有唯一索引且与一条主键冲突与另一条唯一…

瑞_Redis_短信登录_基于Session实现登录流程

文章目录 项目介绍1 短信登录1.1 项目准备1.2 基于Session实现登录流程1.2.1 功能流程介绍1.2.1.1 发送短信验证码1.2.1.2 短信验证码登录、注册1.2.1.3 校验登录状态 1.2.2 实现发送短信验证码功能1.2.2.1 页面流程1.2.2.2 代码实现1.2.2.3 测试 1.2.3 实现短信验证码登录、注…

2024年蓝牙耳机哪个好?真人实测告诉你如何选购,避免后悔!

在繁忙的通勤途中&#xff0c;无线蓝牙耳机已成为我们摆脱线缆束缚、享受音乐的理想选择。面对众多品牌和型号&#xff0c;选择合适的耳机似乎并不简单。因此&#xff0c;我精心挑选了几款表现不错的蓝牙耳机&#xff0c;希望我的分享能为你提供有价值的参考。 一、如何挑选蓝牙…

搭建EMQX MQTT服务器(超详细)

MQTT&#xff08;Message Queuing Telemetry Transport&#xff09;服务器是一种实现 MQTT 协议的服务器软件。MQTT 是一种轻量级的、发布/订阅模式的消息传输协议&#xff0c;通常用于物联网&#xff08;IoT&#xff09;应用中的设备通信。MQTT 服务器负责接收来自客户端的消息…

Java_13 反转字符串中的单词 III(方法一将String改为StringBuilder)

一、反转字符串中的单词 III 给定一个字符串 s &#xff0c;你需要反转字符串中每个单词的字符顺序&#xff0c;同时仍保留空格和单词的初始顺序。 示例 1&#xff1a; 输入&#xff1a;s "Lets take LeetCode contest" 输出&#xff1a;"steL ekat edoCteeL …

数据之谜:解读Facebook的用户行为

在当今数字化时代&#xff0c;社交媒体平台已经成为人们生活中不可或缺的一部分&#xff0c;而Facebook作为全球最大的社交网络之一&#xff0c;其背后隐藏着许多数据之谜。本文将深入探讨Facebook的用户行为&#xff0c;并试图解读其中的奥秘。 用户行为数据的收集 Facebook作…

在Arm 虚拟硬件(AVH)部署深度学习OCR算法

AI算法的嵌入式部署 AI算法在独立的设备上运行其实就是行业内的嵌入式AI的概念, 大致过程如下: 开发AI模型, 2.对数据集进行处理, 3.训练AI模型并验证效果, 4.转成ONNX格式(ONNX:万金油中间格式,给模型优化和部署带来了更多可能性)或者借助libtorch或者TensorFlow来部署C++版…

CSS学习(3)-浮动和定位

一、浮动 1. 元素浮动后的特点 脱离文档流。不管浮动前是什么元素&#xff0c;浮动后&#xff1a;默认宽与高都是被内容撑开&#xff08;尽可能小&#xff09;&#xff0c;而且可以设置宽 高。不会独占一行&#xff0c;可以与其他元素共用一行。不会 margin 合并&#xff0c;…

json字符串的数据提取

json的数据提取 学习目标 掌握 json相关的方法(load loads dump dumps)了解 jsonpath的使用(提取 json中的数据) 2 复习什么是json JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式&#xff0c;它使得人们很容易的进行阅读和编写。同时也方便了机器进行解析和…

【LeetCode: 173. 二叉搜索树迭代器 + dfs + 二叉搜索树】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

docker入门(五)—— 小练习,docker安装nginx、elasticsearch

练习 docker 安装 nginx # 搜素镜像 [rootiZbp15293q8kgzhur7n6kvZ home]# docker search nginx NAME DESCRIPTION STARS OFFICIAL nginx …

SpringBoot中使用验证码easy-captcha

easy-captcha使用的大概逻辑: 当一个请求发送到后端服务器请求验证,服务器使用easy-captcha生成一个验证码图片,并通过session将验证信息保存在服务器,当用户登录校验时候,会从ession中取出对比是否一致 但是前后端分离之后 由于跨域问题 以上就无法实现了 下面这种情况没…

SpringBoot打造企业级进销存储系统 第五讲

package com.java1234.repository;import com.java1234.entity.Menu; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query;import java.util.List;/*** 菜单Repository接口*/ public interface MenuReposit…

【机器学习-05】模型的评估与选择

在前面【机器学习-01】机器学习基本概念与建模流程的文章中我们已经知道了机器学习的一些基本概念和模型构建的流程&#xff0c;本章我们将介绍模型训练出来后如何对模型进行评估和选择等 1、 误差与过拟合 学习器对样本的实际预测结果与真实值之间的差异&#xff0c;我们称之…