在Rust中编写自定义Error的详细代码

 更新时间:2024年01月26日 09:42:29   作者:归云十九少  
Result<T, E> 类型可以方便地用于错误传导,Result<T, E>是模板类型,实例化后可以是各种类型,但 Rust 要求传导的 Result 中的 E 是相同类型的,所以我们需要编写自己的 Error 类型,本文给大家介绍了在Rust中编写自定义Error的详细代码,需要的朋友可以参考下

前言

之前我们聊过,Result<T, E> 类型可以方便地用于错误传导,Result<T, E>是模板类型,实例化后可以是各种类型,但 Rust 要求传导的 Result 中的 E 是相同类型的,或者能够自动转化为相同类型。比如,下面这段代码编译就会报错。所以我们需要编写自己的 Error 类型,以同时包含系统错误和具体业务错误。

use std::io;
use std::fs::{File};

fn read_fs() -> io::Result<()> {
    File::open("abc.txt")?;
    
    Ok(())
}

fn user_err() -> Result<u32, String> {
    Err(String::from("test faill"))
}

fn test() -> Result<u32, String>{
    read_fs()?;
    test()?;
}

pub fn main() {
    test();
}

image.png

系统Error

在 Result<T, E> 中,E 表示一种错误,Rust 标准库已经定义一系列 Error,主要是 io Error。它的定义如下:

pub struct Error {
    repr: Repr,
}

我们可以通过它的关联函数 new,from,other,配合 ErrorKind 来生成一个io Error 用于Reuslt。

自定义 Error

我们要定义一个自己的 Error 类型,它既包含系统的 io Error,也包含业务 Error,定义如下

// 业务 Error 定义
enum WorkError {
  	WorkErrorFirst,
    WorkErrorSecond,
    WorkErrorThird,
}

// 复合 Error 定义
enum MyError {
  	IoErr(std::io::Error),
    WorkErr(WorkError)
}

使用 MyError

fn read_fs() -> Result<(), MyError> {
    let ret = File::open("abc.txt");
    
    if let Err(e) = ret {
        return Err(MyError::IoErr(e));
    } else {
        println!("ret = {ret:?}");
    }
    
    Ok(())
}

fn user_err() -> Result<(), MyError> {
    Err(MyError::WorkErr(WorkError::WorkErrorSecond))
}

fn test() -> Result<(), MyError>{
    read_fs()?;
    user_err()?;
    
    Ok(())
}

pub fn main() {
    let ret = test();
    
    match ret {
        Ok(_) => {
            println!("run test success");
        }
        Err(e) => {
            println!("run test fail");
        }
    }
}

在上述实现中,我们通过手动方式将 std::io::Error 转化为 MyError。也可以通过实现 From trait 来自动实现这种转化。

impl From<std::io::Error> for MyError {
    fn from(err: std::io::Error) -> Self {
        MyError::IoErr(err)
    }
}

// 这样,read_fs 函数就可以简化如下:
fn read_fs() -> Result<(), MyError> {
    File::open("abc.txt")?;
    Ok(())
}

现在还有一个问题,在 main 函数中,我们无法打印 e 信息。通过简单的为 WorkError 和 MyError 类型增加 #[derive(Debug)] 声明,就可以直接打印 e 信息。

到此这篇关于在Rust中编写自定义Error的详细代码的文章就介绍到这了,更多相关Rust编写自定义Error内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • rust延迟5秒锁屏的实现代码

    rust延迟5秒锁屏的实现代码

    这篇文章主要介绍了rust延迟5秒锁屏的实现代码,文中通过实例代码也介绍了rust计算程序运行时间的方法,代码简单易懂,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09
  • Rust动态调用字符串定义的Rhai函数方式

    Rust动态调用字符串定义的Rhai函数方式

    Rust中使用Rhai动态调用字符串定义的函数,通过eval_expression_with_scope实现,但参数传递和函数名处理有局限性,使用FnCall功能更健壮,但更复杂,总结提供了更通用的方法,但需要处理更多错误情况
    2025-02-02
  • Rust使用Channel实现跨线程传递数据

    Rust使用Channel实现跨线程传递数据

    消息传递是一种很流行且能保证安全并发的技术,Rust也提供了一种基于消息传递的并发方式,在rust里使用标准库提供的Channel来实现,下面我们就来学习一下如何使用Channel实现跨线程传递数据吧
    2023-12-12
  • Rust中FFI编程知识点整理总结(推荐)

    Rust中FFI编程知识点整理总结(推荐)

    这篇文章主要介绍了Rust中FFI编程知识点整理总结,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-09-09
  • rust 创建多线程web server的详细过程

    rust 创建多线程web server的详细过程

    web server 中主要的两个协议是 http 和 tcp,tcp 是底层协议,http 是构建在 tcp 之上的,本篇文章重点给大家介绍rust 创建多线程web server的详细过程,感兴趣的朋友跟随小编一起看看吧
    2023-11-11
  • rust标准库std::env环境相关的常量

    rust标准库std::env环境相关的常量

    在本章节中, 我们探讨了Rust处理命令行参数的常见的两种方式和处理环境变量的两种常见方式, 抛开Rust的语法, 实际上在命令行参数的处理方式上, 与其它语言大同小异, 可能影响我们习惯的也就只剩下语法,本文介绍rust标准库std::env的相关知识,感兴趣的朋友一起看看吧
    2024-03-03
  • Rust模块关键词和哈希表详解

    Rust模块关键词和哈希表详解

    文章介绍了Rust编程语言中模块系统、路径控制、as关键字、外部包的使用以及哈希表的操作,主要涵盖了如何通过pub关键字控制模块和结构体的可见性,文章还详细讲解了哈希表的创建、访问、所有权转移、更新操作,感兴趣的朋友一起看看吧
    2026-03-03
  • Rust使用lettre实现邮件发送功能

    Rust使用lettre实现邮件发送功能

    这篇文章主要为大家详细介绍了Rust如何使用lettre实现邮件发送功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2024-11-11
  • Rust语言数据类型的具体使用

    Rust语言数据类型的具体使用

    在Rust中,每个值都有一个明确的数据类型,本文主要介绍了Rust语言数据类型的具体使用,具有一定的参考价值,感兴趣的可以了解一下
    2024-04-04
  • rust交叉编译问题及报错解析

    rust交叉编译问题及报错解析

    这篇文章主要为大家介绍了rust交叉编译问题及报错解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-07-07

最新评论