【Rust自学】9.4. 什么时候该使用panic!

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

9.4.1. 总体原则

在9.1. 不可恢复的错误以及panic!中也讲了Rust中的错误类型有两种:可恢复的和不可恢复的。

调用panic!就相当于发生了一个不可恢复的错误。返回Result类型,这类错误就得到了传播,而且这类错误是可恢复的。

当你认为自己可以替代调用你代码的调用者来决定某些情况是不可恢复的时候,就可以写panic!

如果你写的函数返回的是Result,就相当于你把错误的处理权交给了代码的调用者,调用者就可以根据实际情况来决定是否要恢复这个错误,当然它也可以觉得这个错误是不可恢复的然后调用panic!来进行恐慌。

总而言之,如果你定义的是一个可能失败的函数,那么优先考虑返回Result类型,如果你认为某种情形是肯定不可恢复的,那就使用panic!

9.4.2.panic!适用的场景

编写示例,用于演示某些概念的时候可以使用panic!。在这类程序里面处理错误通常是使用unwrap这类可以制造恐慌的办法。在这里unwrap就相当于一个占位符,然后针对不同功能的不同错误再分别的编写代码进行个性化的处理。

在编写原型代码时可以使用panic!。因为在编写这类代码时还没想好该怎么处理错误, unwrapexpect方法在原型设计时非常方便,因为它们能制造恐慌,在代码中留下清晰的标记,后续就可以根据记号来对这些错误进行进一步的处理。

在编写测试代码时可以使用panic!。因为如果测试代码中的某个方法调用失败了,那么整个测试就应该被认定为失败,而失败状态正可以通过panic!来标记。

9.4.3. 你比编译器更了解情况

有时候你可以确定一个函数的调用返回的Result一定是Ok的,绝对不会出现恐慌,这个时候就可以使用unwrap。但是由于返回类似是Result,所以编译器仍然认为它可能出错,但你知道它一定不可能。

看个例子:

use std::net::IpAddr;
fn main(){let home: IpAddr = "127.0.0.1".parse().unwrap();
}

这个例子使用了IpAddr这个枚举,在main函数中写了"127.0.0.1",对它进行解析,我们知道"127.0.0.1"是一个合理的IP地址,返回值一定是Ok,所以后面就可以使用unwrap,它绝对不会出现恐慌。

9.4.5. 错误处理的指导性建议

当你的代码最终可能处于损坏状态(Bad State)时,最好使用panic!。损坏状态是指某些假设、保证、约定或不可变性被打破了。

比如说一些非法的值、矛盾的值或是空缺的值被传入代码。以及下列中的任意一条:

  • 这种损坏状态是一个意外
  • 在此之后的代码如果处于这种损坏状态就无法运行
  • 使用的类型中没有一个好方法来将这些处于损坏状态的信息进行编码

还是看一下具体的场景:

  • 传入了无意义的参数值:panic!
  • 调用外部不可控代码,返回非法状态,你又无法进行修复:panic!
  • 如果失败是可预期的(比如把字符串解析为数字):Result
  • 当你的代码对值进行操作,首先应该验证值的合法性,如果不合法:panic!
    这一点主要出于安全性的考虑,因为在尝试基于某些非法的值去进行操作的时候,就可能会暴露代码中的漏洞。这也是标准库会在代码尝试越界访问时报错的原因,因为尝试访问不属于当前数据结构的内存是一个普遍的安全问题。
    而且函数通常是有某种约定的,就是只有在输入数据满足某些特定条件下才能够正常运行,而在约定被违反时就应该出发恐慌。因为破坏这些约定往往预示着调用者端产生了bug,而因此产生的错误也不应该由调用者来进行解决,应该就地正法,出发恐慌。

9.4.6. 为验证创建自定义类型

以第二章讲的猜数游戏为例,有些代码不重要就跳过了:

fn main() {loop {// --snip--let guess: i32 = match guess.trim().parse() {Ok(num) => num,Err(_) => continue,};if guess < 1 || guess > 100 {println!("The secret number will be between 1 and 100.");continue;}match guess.cmp(&secret_number) {// --snip--}
}

这里对原本的代码进行了一些修改:

  • guess的值从u32改为i32,这样就能接收负数
  • 对于用户的输入是小于1大于100的情况,提醒用户神秘数字在1到100中间

如果字符串转整形解析失败,那么就会触发continue进行下一次迭代;如果数字的范围不在1到100之间,还会触发continue进行下一次迭代。针对这个小程序,可以把验证直接写在main函数里面,如果是一个大项目,每个函数都需要验证的话,那在每个函数里都写一遍验证逻辑就是相当麻烦的了。

针对这种情况,可以创建一个新的类型,把验证逻辑放到构造这个新类型实例的函数里就行,这样子只有通过验证的才能成功创建出实例,后续不需要担心所接收值的有效性。

看下例子:

pub struct Guess {value: i32,
}impl Guess {pub fn new(value: i32) -> Guess {if value < 1 || value > 100 {panic!("Guess value must be between 1 and 100, got {value}.");}Guess { value }}pub fn value(&self) -> i32 {self.value}
}fn main() {loop {// --snip--let guess: i32 = match guess.trim().parse() {Ok(num) => num,Err(_) => continue,};let guess = Guess::new(guess);match guess.value().cmp(&secret_number) {// --snip--}
}

new就是实例构造器,如果值不在1到100间就会panic!,如果没发生恐慌的话,那就创建一个Guess实例,value的值就是传入的值。

还定义了一个方法叫value,它会提取这个structvalue字段的值返回。

下面的main函数里就可以删掉验证值是否在1到100间的操作了,转而使用Guess::new这个构造器来验证。

如果要使用到guess的实际值,比如说match的时候,就可以使用value这个方法来获取。

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

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

相关文章

Navicat 17 for Mac 数据库管理软件

Mac分享吧 文章目录 效果一、准备工作二、开始安装1. 双击运行软件&#xff0c;将其从左侧拖入右侧文件夹中&#xff0c;等待安装完毕。2. 应用程序/启动台显示Navicat图标&#xff0c;表示安装成功。 二、运行测试运行后提示&#xff1a;“Navicat Premium.pp”已损坏&#x…

Lombok @Data无法 import 导入的问题解决办法

问题原因&#xff1a;Maven Pom中依赖的Lombok版本与安装在eclipse根目录下的Lombok版本不一致 解决办法&#xff1a;找到Maven Pom依赖版本的Lombok Jar包&#xff0c;执行命令&#xff1a;java -jar lombok-1.18.36.jar&#xff0c;运行如下图&#xff0c;然后安装即可。这样…

对计网大题的一些指正(中间介绍一下CDM的原理和应用)

目录 前言&#xff1a; &#xff08;1&#xff09;五层原理体系结构每层功能&#xff1a; 下面是文档的答案&#xff1a; 我在之前的博客里面有介绍过五层原理体系结构&#xff0c; 按理来说&#xff0c;第五层应该是应用层才对&#xff0c;而会话层的功能应该被放到应用层…

RISC-V学习笔记

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

SpringBoot入门之创建一个Hello World项目

文章目录 一、使用传统的方式1、创建一个SpringBoot项目2、配置pom.xml文件3、下载Maven依赖4、创建一个Controller类&#xff1a;com.devops.controller.HelloController5、创建一个引导类&#xff1a;com.devops.HelloApplication6、启动项目8、访问80809、完整项目结构 二、…

三、GIT与Github推送(上传)和克隆(下载)

GIT与Github推送&#xff08;上传&#xff09;和克隆&#xff08;下载&#xff09; 一、配置好SSH二、在Github创建仓库三、git克隆&#xff08;下载&#xff09;文件四、git推送&#xff08;上传&#xff09;文件到远程仓库 一、配置好SSH Git与Github上传和下载时需要使用到…

深入理解属性抽取:实体内部特征信息的挖掘

目录 前言1. 属性抽取的定义与任务1.1 属性抽取的定义1.2 属性抽取的主要任务 2. 属性抽取的技术方法2.1 基于规则的方法2.2 基于机器学习的方法常用模型特征设计 2.3 基于深度学习的方法常用模型架构优势与挑战 2.4 无监督与弱监督方法 3. 属性抽取面临的挑战与应对策略3.1 挑…

145页PPT智慧矿山整体规划建设方案

本资料收录在【智慧方案文库】知识星球&#xff08;截止目前共9500份&#xff0c;PPTWORD超过7000份&#xff0c;持续上传中......&#xff09; 68页PPT丨5G智能矿山解决方案 77页PPT智慧矿山整体规划建设方案

应用架构模式

设计模式 设计模式是指根据通用需求来设计解决方案的模板或蓝图&#xff0c;使用设计模式能够更加有效地解决设计过程中的常见问题。设计模式针对不同的问题域有不同的内涵&#xff0c;主要涉及业务、架构、程序设计等问题域&#xff0c;本文主要讨论架构设计模式。 业务设计模…

以太网ICMP协议(ping指令)——FPGA学习笔记25

--素材来源原子哥 一、IP协议 1、IP简介 IP是Internet Protocol(网际互连协议)的缩写。IP 协议是 TCP/IP 协议簇中的核心协议&#xff0c;它为上层协议提供无状态、无连接、不可靠的服务。IP 协议规定了数据传输时的基本单元和格式 。 IP协议是 OSI 参考模型中网络层…

XIAO ESP32 S3网络摄像头——2视频获取

本文主要是使用XIAO Esp32 S3制作网络摄像头的第2步,获取摄像头图像。 1、效果如下: 2、所需硬件 3、代码实现 3.1硬件代码: #include "WiFi.h" #include "WiFiClient.h" #include "esp_camera.h" #include "camera_pins.h"// 设…

数据看板如何提升决策效率?

数据看板作为一种直观、高效的数据可视化工具&#xff0c;在这一过程中发挥着至关重要的作用。以一家中型制造企业为例&#xff0c;每天面临着生产计划的安排、原材料的采购、产品质量的把控以及市场销售的策略制定等诸多业务场景。在生产线上&#xff0c;需要确保设备的高效运…

javaEE-文件操作和IO-文件

目录 一.什么是文件 1.文件就是硬盘(磁盘)上的文件。 2.计算机中存储数据的设备&#xff1a; 3.硬盘的物理特征 4.树型结构组织和⽬录 5.文件路径 文件路径有两种表示方式&#xff1a; 6.文件的分类 二、java中文件系统的操作 1.File类中的属性&#xff1a; 2.构造方…

【网络安全 | 漏洞挖掘】JS Review + GraphQL滥用实现管理面板访问

未经许可,不得转载。 正文 在映射目标范围后,我发现了一个用于管理的控制台界面,但没有注册功能。 于是我开始尝试: 1、模糊测试注册端点 -> 失败 2、在请求中将登录替换为注册 -> 再次失败 尝试均未奏效后,我决定冷静下来,重新思考方法并利用技术手段。 我观察…

【使用命令配置java环境变量永久生效与脚本切换jdk版本】

java配置环境变量命令与脚本切换jdk版本 新建用户环境变量永久生效 setx JAVA8_HOME "D:\Java\jdk8" setx JAVA17_HOME "d:\Java\jdk-17" setx JAVA_HOME %JAVA8_HOME% setx CLASSPATH ".;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\lib\tools.jar;"…

RabbitMq的Java项目实践

在现代软件开发中&#xff0c;消息队列&#xff08;Message Queue&#xff0c;简称MQ&#xff09;作为一种重要的组件&#xff0c;承担着上下游消息传递和通信的重任。RabbitMQ作为一款流行的开源消息队列中间件&#xff0c;凭借其高可用性、可扩展性和易用性等特点&#xff0c…

《代码随想录》Day25打卡!

《代码随想录》回溯算法&#xff1a;递增子序列 本题的完整题目如下&#xff1a; 本题的完整思路如下&#xff1a; 1.本题使用递归和回溯来求解&#xff0c;所以分为三部&#xff1a; 2.第一步&#xff1a;确定递归函数的返回值和参数&#xff1a;返回值无&#xff0c;参数为原…

Lucas-Kanade光流法详解

简介&#xff1a;个人学习分享&#xff0c;如有错误&#xff0c;欢迎批评指正。 光流&#xff08;Optical Flow&#xff09;描述的是图像序列中各像素点随时间的运动情况&#xff0c;是计算机视觉中的基本问题之一。光流问题涉及尝试找出一幅图像中的许多点在第二幅图像中移动的…

电脑里msvcr120.dll文件丢失怎样修复?

电脑里msvcr120.dll文件丢失的修复指南 在电脑的日常使用中&#xff0c;我们可能会遇到各种各样的系统文件丢失问题&#xff0c;其中msvcr120.dll文件的丢失就是较为常见的一种。作为一名在软件开发领域深耕多年的从业者&#xff0c;我将为大家详细解析msvcr120.dll文件的重要…

windows终端conda activate命令行不显示环境名

问题&#xff1a; 始终不显示环境名 解决 首先需要配置conda的环境变量 确保conda --version能显示版本 然后对cmd进行初始化&#xff0c;如果用的是vscode中的终端&#xff0c;那需要对powershell进行初始化 Windows CMD conda init cmd.exeWindows PowerShell conda …