跟着谷歌安卓团队学Rust - Result更好用的异常处理

143 阅读3分钟

大家好,我是梦兽编程。欢迎回来与梦兽编程一起刷Rust的系列。

这是由 Google 的 Android开发团队的分享Rust课程。本课程涵盖了 Rust 的方方面面,从基本语法到泛型和错误处理等高级主题。

该课程的最新版本可以在 google.github.io/comprehensi…

如果你喜欢看梦兽编程的版本可以订阅跟着谷歌安卓团队学Rust订阅最新内容,梦兽编程也期待大家关注我的个人网站。

加入梦兽编程微信群,公众号回复111即可加入交流群与梦兽进行交流。

Result

在之前我们介绍可以使用Option避免程序出现空指针导致程序的崩溃。但有时候可能因为一个函数会没有做出反应而导致程序崩溃。

例如,如果因为打开一个并不存在的文件而失败,此时我们可能想要创建这个文件,而不是终止进程。

这个时候你就可以使用Result处理这种问题。在Rust中使用Result有点类似golang err。它只有成功和失败两个类型,并不会像Option那样匹配多个Some。

在golang中你可以看到很多err的处理

filePath := "path/to/file.txt"
 file, err := os.Open(filePath)
 if err != nil {
  fmt.Println("打开文件时发生错误:", err)
  return
 }

在Rust中你可以这么理解会比较容易上手。

Result 枚举类型

它又一个Ok和Err组成,按照约定,预期结果是 “Ok”,而意外结果是 “Err”。

enum Result<T, E> {
    Ok(T),
    Err(E),
}

还是以上面golang的例子,在Rust中你可以这么编码。

在没有学习unwrapexpect之前,我们打开文件的时候需要自己处理异常。先获取open后的Result file对象,对其进行match操作。

如果我们确定操作一定会成功,可以使用unwrap方法直接获取Ok中的值;如果我们期望操作成功但有可能失败,可以使用expect方法指定一个错误提示信息。


use std::fs::File;
use std::io::Read;

fn main() {
    let fileResult<File, std::io::Error> = File::open("path/to/file.txt");
    match file {
        Ok(mut file) => {
            let mut contents = String::new();
            if let Ok(bytes) = file.read_to_string(&mut contents) {
                println!("Dear diary: {contents} ({bytes} bytes)");
            } else {
                println!("Could not read file content");
            }
        }
        Err(err) => {
            println!("The diary could not be opened: {err}");
        }
    }
}

我们在看一个之前使用Option的例子,如果使用Result可以这么编码。

fn divide(x: i32, y: i32-> Result<i32String> {
    if y == 0 {
        Err(String::from("division by zero"))
    } else {
        Ok(x / y)
    }
}

fn main() {
    let result = divide(100);
    
    match result {
        Ok(value) => {
            println!("Result: {}", value);
        },
        Err(error) => {
            println!("Error: {}", error);
        }
    }
}

Result类型的应用场景

梦兽编程结合常用开发场景认为可以处理以下场景:

  • 文件读写操作:可以使用Result类型来处理文件读写可能出现的错误,比如文件不存在或权限不足等
  • 网络请求:对于网络请求,可能会出现连接超时、服务器错误等情况,Result类型可以帮助我们处理这些错误
  • 数据库操作:在使用数据库进行增删改查时,可能会出现连接失败、查询语句错误等情况,Result类型可以帮助我们处理这些错误

总结Result类型的优势和注意事项

  1. Result类型强制我们在编码时考虑错误处理的情况,提高程序的健壮性
  2. 使用Result类型能够明确和清晰地处理操作成功和失败的情况
  3. 需要注意正确处理Result类型的所有可能结果,避免出现未处理的错误导致程序崩溃或不可预期的行为

总结Result类型的重要性和灵活性,在编写Rust程序时充分利用Result类型进行错误处理,提高代码的可靠性和可维护性

参考资料

[1]

google.github.io/comprehensi…: google.github.io/comprehensi…

本文使用 markdown.com.cn 排版