Rust 实战thiserror+自定义错误消息体

news2024/9/25 11:16:48

导航

  • 一、背景
  • 二、实践
    • 1、导入thiserror
    • 2、自定义错误消息体
      • (1)创建ErrMsg.rs和创建自定义结构体
      • (2)lib.rs添加ErrMsg
      • (3)main函数
      • (4)完整代码

一、背景

开发中遇到需要通用、能够满足自定义 的错误输出方式,
thiserror是一个不错的工具包,在此基础上我还想加一些自定义的错误消息体,比如HTTP类的错误信息,打印状态码和错误内容

二、实践

1、导入thiserror

thiserror = "1.0"

2、自定义错误消息体

(1)创建ErrMsg.rs和创建自定义结构体

若想能够打印错误信息,为自定义结构体实现display和Debug特征,看完整代码

use crate::Display;
use std::error::Error;
use std::fmt::Debug;
use std::fmt::{self};
// ErrMsg 是自定义错误类型,
// 为 ErrMsg 自动派生 Debug 特征
#[derive(Debug)]
pub struct ErrMsg {
    pub code: u32,
    pub msg: String,
}

// 为 AppError 实现 std::fmt::Display 特征
impl fmt::Display for ErrMsg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ErrMsg: {{code:{},msg :{} }}", self.code, self.msg) // user-facing output
    }
}

pub fn print_err<E>(e: E)
where
    E: Display + Debug + Error,
{
    print!("{}", e);
}

(2)lib.rs添加ErrMsg

// src/lib.rs
pub mod ErrBean;

(3)main函数

使用thiserror 定义枚举,枚举应该包括你需要的所有Error类型

enum MyError {
    #[error("invalid argument: {0}")]
    InvalidArgument(String),
    #[error("io error: {0}")]
    IoError(#[from] std::io::Error),
    #[error("this is display trait  output  :{0}")]//ErrMsg的display的输出,会替换这里的{0}
    ErrMsg(ErrMsg),
}

完整main函数

use hello_package::ErrBean::*;
use std::fmt::{self};
use std::fs::File;
use std::io::{self, Read};
use thiserror::Error;
#[derive(Error, Debug)]
enum MyError {
    #[error("invalid argument: {0}")]
    InvalidArgument(String),
    #[error("io error: {0}")]
    IoError(#[from] std::io::Error),
    #[error("this is display trait  output  :{0}")]
    ErrMsg(ErrMsg),
}
fn read_username_from_file() -> Result<String, MyError> {
    // 打开文件,f是`Result<文件句柄,io::Error>`
    let f = File::open("hello.txt");

    let mut f = match f {
        // 打开文件成功,将file句柄赋值给f
        Ok(file) => file,
        // 打开文件失败,将错误返回(向上传播)
        Err(e) => return Err(MyError::IoError(e)),
    };
    // 创建动态字符串s
    let mut s = String::new();
    // 从f文件句柄读取数据并写入s中
    match f.read_to_string(&mut s) {
        // 读取成功,返回Ok封装的字符串
        Ok(_) => Ok(s),
        // 将错误向上传播
        Err(e) => return Err(MyError::IoError(e)),
    }
}
fn produce_error() -> Result<String, MyError> {
    let err_msg = ErrMsg {
        code: 400,
        msg: String::from("自定义错误内容"),
    };
    Err(MyError::ErrMsg(err_msg))
}

fn main() {
    let res = produce_error();//可以替换成read_username_from_file
    if let Ok(e) = res {
        print!("{}", e);
    } else if let Err(e) = res {
        print!("{}", e);
    }
}

输出结果为

this is display trait  output  :ErrMsg: {code:400,msg :自定义错误内容 }%   

(4)完整代码

为了保证模块化开发,关于错误实体的定义和方法实现应该都放到一个rs文件中,别的文件需要使用时直接导入就好,所以ErrMsg.rs用来定义我们的thiserror和自定义错误消息结构体
ErrMsg.rs

use core::fmt::Display;
use std::error::Error;
use std::fmt::Debug;
use std::fmt::{self};

use thiserror::Error;
#[derive(Error, Debug)]
pub enum MyError {
  #[error("invalid argument: {0}")]//{0}是占位符号,原本error的打印信息会替换这个占位符
  InvalidArgument(String),
  #[error("io error: {0}")]
  IoError(#[from] std::io::Error),
  #[error("this is display trait  output  :{0}")]
  ErrMsg(ErrMsg),
}

// ErrMsg 是自定义错误类型,它可以是当前包中定义的任何类型,在这里为了简化,我们使用了单元结构体作为例子。
// 为 ErrMsg 自动派生 Debug 特征
#[derive(Debug)]
pub struct ErrMsg {
    pub code: u32,
    pub msg: String,
}

// 为 ErrMsg 实现 std::fmt::Display 特征
impl fmt::Display for ErrMsg {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "ErrMsg: {{code:{},msg :{} }}", self.code, self.msg) // user-facing output
    }
}

pub fn print_err<E>(e: E)
where
    E: Display + Debug + Error,
{
    print!("{}", e);
}

main.rs

use hello_package::ErrBean::*;
use std::fmt::{self};
use std::fs::File;
use std::io::{self, Read};

fn read_username_from_file() -> Result<String, MyError> {
    // 打开文件,f是`Result<文件句柄,io::Error>`
    let f = File::open("hello.txt");

    let mut f = match f {
        // 打开文件成功,将file句柄赋值给f
        Ok(file) => file,
        // 打开文件失败,将错误返回(向上传播)
        Err(e) => return Err(MyError::IoError(e)),
    };
    // 创建动态字符串s
    let mut s = String::new();
    // 从f文件句柄读取数据并写入s中
    match f.read_to_string(&mut s) {
        // 读取成功,返回Ok封装的字符串
        Ok(_) => Ok(s),
        // 将错误向上传播
        Err(e) => return Err(MyError::IoError(e)),
    }
}
fn produce_error() -> Result<String, MyError> {
    let err_msg = ErrMsg {
        code: 400,
        msg: String::from("自定义错误内容"),
    };
    Err(MyError::ErrMsg(err_msg))
}

fn main() {
    let res = produce_error();
    if let Ok(e) = res {
        print!("{}", e);
    } else if let Err(e) = res {
        print!("{}", e);
    }
}

在这里插入图片描述

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

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

相关文章

发卡授权盗u源码系统搭建ZHU16728

2024最新UI发卡盗U/支持多语言/更新UI界面/支持多个主流钱包去除后门板&#xff0c;搭建系统TGaqxm01 。功能完美。 此套系统二开后完美授权成功&#xff0c;百分百授权。不是市面上那种授不了权的那种。 授权额度Unlimited 懂的都懂。 1.Php静态 2.目录puicta 3.扩sal 4.ss…

避雷!7.7分,新增1区TOP被标记On Hold,5本已被踢除!

本周投稿推荐 SSCI • 2/4区经管类&#xff0c;2.5-3.0&#xff08;录用率99%&#xff09; SCIE&#xff08;CCF推荐&#xff09; • 计算机类&#xff0c;2.0-3.0&#xff08;最快18天录用&#xff09; SCIE&#xff08;CCF-C类&#xff09; • IEEE旗下&#xff0c;1/2…

Mysql索引失效情况

索引失效的情况 这是正常查询情况&#xff0c;满足最左前缀&#xff0c;先查有先度高的索引。 1. 注意这里最后一种情况&#xff0c;这里和上面只查询 name 小米科技 的命中情况一样。说明索引部分丢失&#xff01; 2. 这里第二条sql中的&#xff0c;status > 1 就是范围查…

【图书推荐】《ChatGLM3大模型本地化部署、应用开发与微调》

本书目的 本书通过多个PyTorch实战案例&#xff0c;帮助读者掌握ChatGLM3大模型本地化部署、应用开发与微调技能。智能问答机器人、美妆助手、上市公司财务报表信息抽取、上市公司财务报表智能问答与财务预警等案例&#xff0c;都可以按读者自己的业务需求&#xff0c;改造成可…

Ubuntu多版本(低版本)gcc/g++安装、切换与卸载图文教程

目录 1 问题背景2 多版本安装3 多版本切换4 多版本卸载5 其他问题 1 问题背景 环境&#xff1a; gcc 9.4.0g 9.4.0Ubuntu20.04 现象&#xff1a;通过apt install build-essential安装的gcc和g默认是当前版本系统支持的最高版本编译器&#xff0c;但是很多工程的编译需要安装低版…

大数据信用风险特别高,那大数据信用高风险要如何降低呢?

在大数据信用报告中&#xff0c;综合评分是直观体现信用风险高低的重要元素&#xff0c;也就是我们长听说的大数据信用分&#xff0c;很多人在查大数据信用报告之后&#xff0c;发现自己的大数据信用风险特别高&#xff0c;那大数据信用高风险要如何降低呢?小编从引起高风险的…

在线点餐系统搭建重点,会用到哪些三方服务?

在线点餐系统的搭建是一个涉及多个环节和技术的过程&#xff0c;其重点包括需求分析、系统设计、功能实现、用户体验以及系统的稳定性和安全性等方面。在搭建过程中&#xff0c;可能会使用到以下三方服务&#xff1a; 云服务提供商&#xff1a;云服务为在线点餐系统提供了基础…

充电宝怎么选?哪些充电宝的性价比比较高?性价比高充电宝推荐

在快节奏的现代生活中&#xff0c;共享充电宝已成为我们出行的常见伴侣。它们遍布城市的各个角落&#xff0c;为手机电量告急的我们提供了及时的帮助。然而&#xff0c;这种便利背后也隐藏着一些不那么方便的小插曲。 首先&#xff0c;我们得承认共享充电宝的便捷性。无论你是…

【JavaEE 初阶(二)】线程安全问题

❣博主主页: 33的博客❣ ▶️文章专栏分类:JavaEE◀️ &#x1f69a;我的代码仓库: 33的代码仓库&#x1f69a; &#x1faf5;&#x1faf5;&#x1faf5;关注我带你了解更多线程知识 目录 1.前言2.synchronized2.1例子2.2synchronized修饰代码块2.3 synchronized修饰方法2.4sy…

多模态路径:利用其他模态的无关数据改进变压器(CVPR 2024)

<Multimodal Pathway: Improve Transformers with Irrelevant Data from Other Modalities> 论文地址&#xff1a;https://arxiv.org/abs/2401.14405 项目网页&#xff1a;https://ailab-cvc.github.io/M2PT/ 开源代码&#xff1a;https://github.com/AILab-CVC/M2PT 讲…

天锐绿盾 | 公司防泄密软件

天锐绿盾是一款专为企业设计的图纸及文件加密防泄密软件&#xff0c;旨在保护企业的核心信息资产和知识产权。这款软件提供了强大的数据保护功能&#xff0c;通过透明加密技术&#xff0c;在不影响员工正常工作流程的前提下&#xff0c;自动对指定类型的文件&#xff08;如设计…

流程:采集1688店铺内有成交的商品列表||1688商品订单列表+订单详情API接口

此API目前支持以下基本接口&#xff1a; item_get 获得1688商品详情item_search 按关键字搜索商品item_search_img 按图搜索1688商品&#xff08;拍立淘&#xff09;item_search_suggest 获得搜索词推荐item_fee 获得商品快递费用seller_info 获得店铺详情item_search_shop 获得…

【intro】图卷积神经网络(GCN)

本文为Graph Neural Networks(GNN)学习笔记-CSDN博客后续&#xff0c;内容为GCN论文阅读&#xff0c;相关博客阅读&#xff0c;kaggle上相关的数据集/文章/代码的阅读三部分&#xff0c;考虑到本人是GNN新手&#xff0c;会先从相关博客开始&#xff0c;进一步看kaggle&#xff…

618有哪些你值得入手的?你值得入手的618好物清单

在618的折扣风暴中&#xff0c;我特别想向那些计划更新家电的朋友们推荐一些优质产品。家电作为日常生活中不可或缺的一部分&#xff0c;其品质与性价比尤为重要。而618正是购买家电的绝佳时机&#xff0c;但如何避免被次品所困&#xff0c;这就需要你手握这份618好物清单&…

《MySQL数据类型》

文章目录 一、理解数据本身就是一种约束1.tinyint类型和 tinyint unsigned类型2.其他的int类型 二、bit类型三、float类型1.signed版本注意2.unsigned版本 四、decimal类型float 和 decimal 总结五、char类型&#xff08;固定长度&#xff09;六、varchar类型&#xff08;可变长…

T型槽地轨承载力是如何连接整个制造过程的强力桥梁(北重公司设计)

T型槽地轨承载力的定义和计算 T型槽地轨是一种用于工业设备运输和装配的关键组件。它由世界上各行各业的生产商广泛采用&#xff0c;其有效的承载力使其成为连接整个制造过程的强力桥梁。本文将介绍T型槽地轨的承载力以及相关的设计要点和应用。 承载力的定义和计算 承载力是…

IDEA--debug

1. 单点调试的三个级别 Step into&#xff1a;在单步执行时&#xff0c;遇到子函数就进入并且继续单步执行。Step over&#xff1a;在单步执行时&#xff0c;在函数内遇到子函数时不会进入子函数内单步执行&#xff0c;而是将子函数整个执行完再停止&#xff0c;也就是把子函数…

商品期权交易怎么操作?

今天期权懂带你了解商品期权交易怎么操作&#xff1f;作为金融市场中的一种重要衍生品&#xff0c;商品期权在风险管理、套期保值和投机交易中发挥着重要的作用。 商品期权交易怎么操作&#xff1f; 选择期权合约&#xff1a;根据市场分析结果&#xff0c;选择合适的期权合约进…