Rust5.1 Error Handling

Rust学习笔记

Rust编程语言入门教程课程笔记

参考教材: The Rust Programming Language (by Steve Klabnik and Carol Nichols, with contributions from the Rust Community)

Lecture 9: Error Handling

use std::error::Error;
use std::io::ErrorKind;
use std::fs::File;
use std::io::Read;
use std::net::IpAddr;
use std::io;


fn main() -> Result<(), Box<dyn Error>> {//Box<dyn Error> means the function will return a type that implements the Error trait

    // Rust groups errors into two major categories: recoverable and unrecoverable errors.
    // For a recoverable error, such as a file not found error, it’s reasonable to report
    // the problem to the user and retry the operation. Unrecoverable errors are always
    // symptoms of bugs, like trying to access a location beyond the end of an array.

    // Recoverable errors are instances of the Result<T, E> enum, which has variants
    // Ok(T), representing success and containing a value, and Err(E), representing error
    // and containing an error value. The Result<T, E> enum is defined as part of the
    // standard library.

    // The panic! macro can be used to generate a panic and start unwinding its stack.
    // While unwinding, the runtime will take care of freeing all the resources owned by
    // the thread by calling the destructors of all its objects.

    let f = File::open("hello.txt");
    match f {
        Ok(file) => file,
        Err(error) => panic!("Problem opening the file: {:?}", error),
    };

    let _f = File::open("hello.txt").unwrap();//unwrap returns the Ok value inside the Ok variant
    //unwrap cannot define the type of the error so it will panic if it is Err

    let _f = File::open("hello.txt").expect("Failed to open hello.txt");//expect is similar to unwrap but it allows us to choose the panic message

    //matching on different errors
    let f = File::open("hello.txt");
    let _f = match f {
        Ok(file) => file,
        Err(error) => match error.kind() {
            ErrorKind::NotFound => match File::create("hello.txt") {
                Ok(fc) => fc,
                Err(error) => panic!("Problem creating the file: {:?}", error),
            },
            other_error => panic!("Problem opening the file: {:?}", other_error),
        },
    };

    let _f = File::open("hello.txt").unwrap_or_else(|error| {//unwrap_or_else takes a closure
        if error.kind() == ErrorKind::NotFound {
            File::create("hello.txt").unwrap_or_else(|error| {
                panic!("Problem creating the file: {:?}", error);
            })
        } else {
            panic!("Problem opening the file: {:?}", error);
        }
    });

    //propagating errors
    let _ = read_username_from_file();

    //shortcut for propagating errors: the ? operator
    let _ = _read_username_from_file();
    //the ? operator can only be used in functions that return Result

    //translating errors from one type into another using From trait
    //when implementing the From trait, the standard library provides a generic
    //implementation of From<T> for any type T that implements the Into<U> trait
    //this is useful when we want to return a specific error type but the function
    //we are calling returns a generic error type

    //panic! vs Result

    let _home: IpAddr = "127.0.0.1"
        .parse()
        .expect("Hardcoded IP address should be valid");

    //create a custom type for the error
    let guess = Guess::new(99);//the constructor will check if the value is valid
    println!("Guess value: {}", guess.value());

    //use ? in main
    let _greeting_file = File::open("hello.txt")?;
    Ok(()) //fn main() -> Result<(), Box<dyn Error>> 
}

fn read_username_from_file() -> Result<String, io::Error> {
    let f = File::open("hello.txt");
    let mut f = match f {
        Ok(file) => file,
        Err(e) => return Err(e),//early return
    };

    let mut s = String::new();

    match f.read_to_string(&mut s) {
        Ok(_) => Ok(s),
        Err(e) => Err(e),//early return
    }
}

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 {//we need to return a reference to the value
        self.value
    }
}

fn _read_username_from_file() -> Result<String, io::Error> {
    let mut f = File::open("hello.txt")?;//? can only be used in functions that return Result
    let mut s = String::new();
    f.read_to_string(&mut s)?;//? can only be used in functions that return Result
    Ok(s)
}   //? can be chained to simplify the code
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Rust的actix-web框架中,`Responder`和`ResponseError`是用于处理HTTP响应的重要trait。它们允许你定义如何将数据转换为HTTP响应以及如何处理错误。 `Responder` trait用于将数据转换为HTTP响应。你可以在自定义的类型上实现`Responder` trait,以便该类型可以直接返回给actix-web的处理器函数。以下是一个示例: ```rust use actix_web::{HttpResponse, Responder}; struct MyData { // 数据结构 } impl Responder for MyData { type Error = actix_web::Error; type Future = Result<HttpResponse, Self::Error>; fn respond_to(self, _: &actix_web::HttpRequest) -> Self::Future { // 将数据转换为HttpResponse let response = HttpResponse::Ok().json(self); // 假设MyData实现了serde的Serialize trait Ok(response) } } ``` 在这个示例中,我们为自定义的`MyData`类型实现了`Responder` trait。我们通过实现`respond_to`方法来定义如何将数据转换为HTTP响应。在这个例子中,我们使用`HttpResponse::Ok().json(self)`将`MyData`转换为JSON格式的HTTP响应。 `ResponseError` trait用于处理错误并生成适当的HTTP响应。你可以在自定义的错误类型上实现`ResponseError` trait,以便actix-web可以捕获并处理这些错误。以下是一个示例: ```rust use actix_web::{HttpResponse, ResponseError}; use std::convert::From; #[derive(Debug)] struct MyError { // 错误信息 } impl ResponseError for MyError { fn error_response(&self) -> HttpResponse { // 生成适当的HTTP响应 HttpResponse::InternalServerError().body("Internal Server Error") } } impl From<actix_web::Error> for MyError { fn from(_: actix_web::Error) -> Self { MyError { // 从actix-web的Error转换为自定义的错误类型 } } } ``` 在这个示例中,我们为自定义的`MyError`类型实现了`ResponseError` trait。我们通过实现`error_response`方法来定义如何生成适当的HTTP响应。在这个例子中,我们直接返回一个带有"Internal Server Error"消息的500错误响应。 另外,我们还实现了`From<actix_web::Error>` trait,以便将actix-web的错误转换为我们自定义的错误类型。这样,在处理请求时,actix-web可以自动将错误转换为我们定义的`MyError`类型。 希望这可以帮助你理解和使用`Responder`和`ResponseError` trait!如果还有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值