首页 > 其他分享 >Result | Option | unwrap | ?

Result | Option | unwrap | ?

时间:2023-11-30 17:26:44浏览次数:43  
标签:serde Option Err unwrap json let Result

原文链接

1、Option - 可空变量

虽然Rust中有null的概念,但是使用null并不是Rust中常见的模式。假设我们要写一个函数,输入一种手机操作系统的名称,这个函数就会返回其应用商店的名称。如果传入字符串iOS,该函数将返回App Store;如果传入字符串android,那么该函数将返回Play Store。任何其他的输入都被视为无效。

在大多数开发语言中,我们可以选择返回null或字符串invalid来表示无效的结果,不过这不是Rust的用法。

地道的Rust代码应该让该函数返回一个OptionOption或更确切的说Option<T>是一个泛型,可以是Some<T>None(为了便于阅读,后续文章中将省略类型参数T)。Rust将SomeNone称为变体(Variant) —— 这一概念在其他语言中并不存在,因此我也不 去定义到底什么是变体了。

在我们的示例中,正常情况下函数将返回包裹在Some变体中的字符串常量App Store或Play Store。而在非正常情况下,函数将返回None。

fn find_store(mobile_os: &str) -> Option<&str> {
    match mobile_os {
        "iOS" => Some("App Store"),
        "android" => Some("Play Store"),
        _ => None
    }
}

要使用find_store(),我们可以用如下方式调用:

fn main() {
    println!("{}", match find_store("windows") {
        Some(s) => s,
        None => "Not a valid mobile OS"
    });
}

2、Result - 包含错误信息的结果

Result,或者更确切地说Result<T,E>,是和Rust中的Option相关的概念,它是一个加强版本的Option。

Result<T, E>可能有以下结果之一:

  • Ok(T):结果为成员T
  • Err(E):结果为故障成员E

与之前我们看到Option<T>可以包含Some<T>或None不同,Result中包含了错误相关信息,这是Option中所没有的。

让我们看一个函数实例,它返回一个Result。该函数摘自用于解析JSON字符串的serde_json库,其签名为

pub fn from_str<'a, T>(s: &'a str) -> Result<T, Error> 
where
    T: Deserialize<'a>,

假设我们要解析如下的字符串:

let json_string = r#"
    {
        "name": "John Doe",
        "age": 43,
        "phones": [
            "+44 1234567",
            "+44 2345678"
        ]
    }"#;

目标是解析为Rust的一个person结构对象:

#[derive(Serialize, Deserialize)]
struct Person {
    name: String,
    age: u8,
    phones: Vec<String>,
}

解析过程的Rust代码如下:

let p:Person = match serde_json::from_str(json_string) {
    Ok(p) => p,
    Err(e) => ... //we will discuss what goes here next 
};

正常情况下可以得到期望的结果。不过假设在输入的json_string中有一个笔误,这导致程序运行时将执行Err分支。

当碰到Err时,我们可以采取两个动作:

  • panic!
  • 返回Err

3、unwrap - 故障时执行panic!

在上面的示例中,假设我们期望panic!:

let p: Person = match serde_json::from_str(data) {
        Ok(p) => p,
        Err(e) => panic!("cannot parse JSON {:?}, e"), //panic
    }

当碰到Err时,上面的代码panic!就会崩掉整个程序,也许这不是你期望的。我们可以修改为:

let p:Person = serde_json::from_str(data).unwrap();

如果我们可以确定输入的json_string始终会是可解析的,那么使用unwrap没有问题。但是如果会出现Err,那么程序就会崩溃,无法从故障中恢复。在开发过程中,当我们更关心程序的主流程时,unwrap也可以作为快速 原型使用。

因此unwrap隐含了panic!。虽然与更显式的版本没有差异,但是危险在于其隐含特性,因为有时这并不是你真正期望的行为。

无论如何,如果我们需要调用panic!,代码如下:

use serde::{Deserialize, Serialize};
use serde_json::Result;

#[derive(Serialize, Deserialize)]
struct Person {
    name: String,
    age: u8,
    phones: Vec<String>,
}

fn typed_example() -> Result<()> {
    //age2 is error on purpose
    let data = r#"
        {
            "name": "John Doe",
            "age2": 43,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;

    let p:Person = serde_json::from_str(data).unwrap();

    println!("Please call {} at the number {}", p.name, p.phones[0]);

    Ok(())
}

fn main() {
    match typed_example() {
        Ok(_) => println!("program ran ok"),
        Err(_) => println!("program ran with error"),
    }
}

4、? - 故障时返回Err对象

当碰到Err时,我们不一定要panic!,也可以返回Err。不是每个Err都是不可恢复的,因此有时并不需要panic!。下面的代码返回Err:

let p: Person = match serde_json::from_str(data) {
        Ok(p) => p,
        Err(e) => return Err(e.into()),
};

?操作符提供了一个更简洁的方法来替换上面的代码:

let p:Person = serde_json::from_str(data)?;

这时完整的Rust程序代码如下:

use serde::{Deserialize, Serialize};
use serde_json::Result;

#[derive(Serialize, Deserialize)]
struct Person {
    name: String,
    age: u8,
    phones: Vec<String>,
}

fn typed_example() -> Result<()> {
    //age2 is error on purpose
    let data = r#"
        {
            "name": "John Doe",
            "age2": 43,
            "phones": [
                "+44 1234567",
                "+44 2345678"
            ]
        }"#;

    let p: Person = serde_json::from_str(data)?;

    println!("Please call {} at the number {}", p.name, p.phones[0]);

    Ok(())
}

fn main() {
    match typed_example() {
        Ok(_) => println!("program ran ok"),
        Err(e) => println!("program ran with error {:?}", e),
    }
}

5、使用unwrap和?解包Option

就像我们可以使用unwarp和?来处理Result,我们也可以使用unwrap和?来处理Option。

如果我们unwrap的Option的值是None,那么程序就会panic!。示例如下:

fn next_birthday(current_age: Option<u8>) -> Option<String> {
    // If `current_age` is `None`, this returns `None`.
    // If `current_age` is `Some`, the inner `u8` gets assigned to `next_age` after 1 is added to it
    let next_age: u8 = current_age?;
    Some(format!("Next year I will be {}", next_age + 1))
}

fn main() {
  let s = next_birthday(None);
  match s {
      Some(a) => println!("{:#?}", a),
      None => println!("No next birthday")
  }
}

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

标签:serde,Option,Err,unwrap,json,let,Result
From: https://www.cnblogs.com/imreW/p/17867816.html

相关文章

  • [English]phonetic/adoption/rote/nursery
    Phonetic describesthewaythatspokenwordssound.AdoptioncomesfromtheOldFrenchwordadoptare,meaning"tochoseforoneself.”Feellikeaddinganoption?Ifyoustartdressinglikeafriend,that'sanadoptionofyourfriend's......
  • Android-ActivityResultAPI
    Android-ActivityResultAPI1.推出目的如果你将项目中的appcompat库升级到1.3.0或更高的版本,你会发现startActivityForResult()方法已经被废弃了。现在更加建议使用ActivityResultAPI来实现在两个Activity之间交换数据的功能。2.传统写法-在两个Activity之间交换数据如......
  • VisionPro学习笔记(5)——极轴展开工具PolarUnwrapTool
    如果需要了解其他图像处理的文章,请移步小编的GitHub地址传送门:请点击我如果点击有误:https://github.com/LeBron-Jian/ComputerVisionPracticeVisionPro有很多的示例和算子,这里展示一个基础的算子PolarUnwrapTool。我自己的笔记不会按照顺序一一展示出来的,也许那......
  • JQuery获取select点击option的data-*属性
    <optionvalue="33333"data-socketid="1111"data-numnew="22222">4444</option>$(document).on('change','#institute-select',function(){//这里是重点,使用attr来获取vari......
  • Angular 依赖注入领域里 optional constructor parameters 的概念介绍
    Angular依赖注入(DI)是一个强大且灵活的设计模式,它可以帮助我们更好地管理和组织我们的代码。构造函数参数的可选性(Optional)是AngularDI系统的一个重要特性。这种特性允许我们将某些服务或值作为可选依赖注入到组件或服务中,这样,如果这些服务或值不存在,我们的代码仍然可以正常工......
  • Android深入学习之ComponentActivity.registerForActivityResult()方法
    ComponentActivity.startActivityForResult()和ComponentActivity.onActivityResult()已经废弃,如下图所示,取而代之的是统一它俩的ActivityResultLauncher。  ActivityResultLauncher对象可以通过ComponentActivity.registerForActivityResult()方法获取。该方法有两个重载。......
  • 企业微信——给国外的邮箱发邮件报错Authentication results: DKIM = did not pass
    前言发件人([email protected])域名的DNS记录未设置或设置错误导致对方拒收此邮件。hostgmail-smtp-in.l.google.com[172.253.118.27]said:550-5.7.26Thismailhasbeenblockedbecausethesenderisunauthenticated.Gmailrequiresallsenderstoauthenticatewitheither......
  • idea报错Java HotSpot(TM) 64-Bit Server VM warning Options -Xverifynone and -nove
    问题描述我的:IDEA的版本为:2021.3‍最近在使用idea运行SpringBoot时,idea总是显示报错信息,报错信息如下:‍​​‍解决方法‍第一步:选择下图的EditConfigurations‍​​‍第二步:在跳转出的界面中找到Modifyoptions这个选项,点进去‍​​‍第......
  • WEBSITE_LOCAL_CACHE_OPTION Environment variables and app settings in Azure App S
    EnvironmentvariablesandappsettingsinAzureAppService SettingnameDescriptionWEBSITE_LOCAL_CACHE_OPTIONWhetherlocalcacheisenabled.Availableoptionsare:-Default:Inheritthestamp-levelglobalsetting.-Always:Enablefortheapp.......
  • Option B
    设想一个场景:别人做好了一个ppt,需要你上去讲。你过了一遍ppt后,发现逻辑有问题,结论不成立。这时距离上台讲只剩下20分钟了,该怎么办?面对这个情况,我就犯了错误,总想着去圆ppt的思路,而忽略了自己的思路。其实不管ppt是谁做的,你上台讲,你所输出的代表的就是你的逻辑和结论。因......