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

news2025/1/6 11:13:13

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

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.coloradmin.cn/o/2270962.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ROS功能包开机自启动(2步解决)

为了实现小车在开机后能自动启动相关功能模块需要解决两个问题 1.准备启动脚本文件加载对应的rosnode和roslaunch&#xff0c;整合相关节点按需要顺序进行&#xff0c;防止报错 2.设置开启启动脚本相关内容 既然是自启动&#xff0c;不能避免USB数据传输的一些问题&#xff…

【ArcGISPro/GeoScenePro】解决常见的空间参考和投影问题

修复空间参考缺失的图像 数据 https://arcgis.com/sharing/rest/content/items/535efce0e3a04c8790ed7cc7ea96d02d/data 查看属性坐标 查看属性范围 范围值并不是零或接近于零。 这意味着栅格具有范围,因此其已正确进行

NLP 中文拼写检测纠正论文-08-Combining ResNet and Transformer

拼写纠正系列 NLP 中文拼写检测实现思路 NLP 中文拼写检测纠正算法整理 NLP 英文拼写算法&#xff0c;如果提升 100W 倍的性能&#xff1f; NLP 中文拼写检测纠正 Paper java 实现中英文拼写检查和错误纠正&#xff1f;可我只会写 CRUD 啊&#xff01; 一个提升英文单词拼…

【paddle】初次尝试

张量 张量是 paddlepaddle&#xff0c; torch&#xff0c; tensorflow 等 python 主流机器学习包中唯一通货变量&#xff0c;因此应当了解其基本的功能。 张量 paddle.Tensor 与 numpy.array 的转化 import paddle as paddle import matplotlib.pyplot as plt apaddle.to_t…

如何在谷歌浏览器中使用屏幕录制功能

在日常使用电脑的过程中&#xff0c;我们经常会遇到需要记录屏幕操作的情况。无论是制作教学视频、保存游戏过程还是记录会议内容&#xff0c;谷歌浏览器的屏幕录制功能都能帮助我们轻松实现这些需求。那么&#xff0c;如何在谷歌浏览器中启用并使用屏幕录制功能呢&#xff1f;…

万里数据库GreatSQL监控解析

GreatSQL是MySQL的一个分支&#xff0c;专注于提升MGR&#xff08;MySQL Group Replication&#xff09;的可靠性及性能。乐维监控平台可以有效地监控GreatSQL&#xff0c;帮助用户及时发现并解决潜在的性能问题。 通过在GreatSQL服务器上安装监控代理&#xff0c;收集数据库性…

APM 3.0.2 | 聚合B站、油管和MF的音乐播放器,支持歌词匹配

APM&#xff08;Azusa-Player-Mobile&#xff09;是一款基于B站的第三方音频播放器&#xff0c;现已扩展支持YouTube Music、YouTube、本地音乐、AList和MusicFree等平台。它不仅提供视频作为音频播放&#xff0c;还具备排行榜、分区动态等功能。用户可以通过添加Alist地址接入…

HTML——61. 单行文本框和密码输入框(主讲input元素的type属性)

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>单行文本框和密码输入框</title></head><body><!--input元素的type属性&#xff1a;(必须要有)--> <!--单行文本框:1.type"text"2.可…

在Typora中实现自动编号

文章目录 在Typora中实现自动编号1. 引言2. 准备工作3. 自动编号的实现3.1 文章大纲自动编号3.2 主题目录&#xff08;TOC&#xff09;自动编号3.3 文章内容自动编号3.4 完整代码 4. 应用自定义CSS5. 结论 在Typora中实现自动编号 1. 引言 Typora是一款非常流行的Markdown编辑…

微机——计算机中的数制

目录 数制转换&#xff1a; 十进制数转为非十进制数&#xff1a; 二、八、十六进制数之间的转换&#xff1a; 数及字符的表示&#xff1a; 二进制数的加减运算&#xff1a; 无符号数的运算&#xff1a; 带符号数运算中的溢出问题&#xff1a; 计算机中常用的编码&#…

设计心得——流程图和数据流图绘制

一、流程图和数据流图 在软件开发中&#xff0c;画流程图和数据流图可以说是几乎每个人都会遇到。 1、数据流&#xff08;程&#xff09;图 Data Flow Diagram&#xff0c;DFG。它可以称为数据流图或数据流程图。其主要用来描述系统中数据流程的一种图形工具&#xff0c;可以将…

Node 如何生成 RSA 公钥私钥对

一、引入crypto模块 crypto 为node 自带模块&#xff0c;无需安装 const crypto require(crypto);二、封装生成方法 async function generateRSAKeyPair() {return new Promise((resolve, reject) > {crypto.generateKeyPair(rsa, {modulusLength: 2048, // 密钥长度为 …

壁纸样机神器,可以导出高清图片吗?

壁纸样机神器确实支持导出高清图片。根据搜索结果中的信息&#xff0c;壁纸样机神器提供了以下功能&#xff1a; 壁纸样机神器免费体验 高清壁纸上传&#xff1a;壁纸样机神器支持上传您自己的壁纸图片&#xff0c;推荐尺寸为1290 2796&#xff08;9:19.5&#xff09;&#xf…

数据挖掘——神经网络分类

神经网络分类 神经网络分类人工神经网络多层人工神经网络 误差反向传播&#xff08;BP&#xff09;网络后向传播算法 神经网络分类 人工神经网络 人工神经网络主要由大量的神经元以及它们之间的有向连接构成。包含三个方面&#xff1a; 神经元的激活规则 主要是指神经元输入…

快速上手LangChain(三)构建检索增强生成(RAG)应用

文章目录 快速上手LangChain(三)构建检索增强生成(RAG)应用概述索引阿里嵌入模型 Embedding检索和生成RAG应用(demo:根据我的博客主页,分析一下我的技术栈)快速上手LangChain(三)构建检索增强生成(RAG)应用 langchain官方文档:https://python.langchain.ac.cn/do…

Json字符串解析失败

通过第三方服务&#xff0c;拿到响应体的data对象&#xff08;拿到的时候对象是有值的&#xff09; 通过JSON.parseObject方法&#xff0c;拿到的对象&#xff0c;值为null 通过查看对应的json字符串&#xff0c;发现命名不一样... JSONField SeriealizedName注解是用来解析j…

网络安全 | 信息安全管理体系(ISMS)认证与实施

网络安全 | 信息安全管理体系&#xff08;ISMS&#xff09;认证与实施 一、前言二、信息安全管理体系&#xff08;ISMS&#xff09;概述2.1 ISMS 的定义与内涵2.2 ISMS 的核心标准 ——ISO/IEC 27001 三、信息安全管理体系&#xff08;ISMS&#xff09;认证3.1 认证的意义与价值…

《黄药师》药业管理软件 UploadFile 文件上传致RCE漏洞复现

0x01 产品简介 《黄药师》药业管理软件是一款针对我国医药或医疗器械企业经营管理特点而设计的综合管理软件。《黄药师》系列管理软件集进销存、财务、经营分析和GSP管理为一体,从企业经营的各个环节对资金流、物流、信息流等进行系统的管理。它采用“一看就懂,一学就会,一…

电子应用设计方案84:智能 AI 煤气灶系统设计

智能 AI 煤气灶系统设计 一、引言 智能 AI 煤气灶系统旨在提供更安全、便捷和高效的烹饪体验&#xff0c;结合人工智能技术实现智能化的控制和管理。 二、系统概述 1. 系统目标 - 精确控制火力大小&#xff0c;实现精准烹饪。 - 具备智能防干烧和熄火保护功能&#xff0c;确保…

带虚继承的类对象模型

文章目录 1、代码2、 单个虚继承3、vbptr是什么4、虚继承的多继承 1、代码 #include<iostream> using namespace std;class Base { public:int ma; };class Derive1 :virtual public Base { public:int mb; };class Derive2 :public Base { public:int mc; };class Deri…