scanf返回值被忽略是什么意思_Rust语言中的Result:不得不处理的返回值

在编写程序的时候,常常因为疏忽或者懒惰没有处理函数调用的返回值,给代码的稳定性增添了隐患。如果是Rust编程,你不用有这样的顾虑。或许有些人可能认为这样coding太烦人了。不过和程序的健壮性相比,这又算得了什么呢。

Result<T, E> 是一个用来返回值和成功、错误值的类型:携带变量的枚举类型。 Ok(T)表示成功,并且包含返回值, T表示正确的返回值变量的类型(T为泛型);Err(E)表示失败,并且包含了返回值,E表示错误的返回值的类型(泛型)。

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

如果函数处理过程中可能会遇到预期的错误,则函数定义中需要返回result。调用方需要解析Reuslt携带的值。看一个Result的栗子

#[derive(Debug)]
enum Version { Version1, Version2 }

fn parse_version(header: &[u8]) -> Result<Version, &'static str> {
    match header.get(0) {
        None => Err("invalid header length"),
        Some(&1) => Ok(Version::Version1),
        Some(&2) => Ok(Version::Version2),
        Some(_) => Err("invalid version"),
    }
}

let version = parse_version(&[1, 2, 3, 4]);
match version {
    Ok(v) => println!("working with version: {:?}", v),
    Err(e) => println!("error parsing header: {:?}", e),
}

对于简单的case来说,使用模式匹配来处理result是清晰和直接的。然而result还有一些更简洁的方法:

let good_result: Result<i32, i32> = Ok(10);
let bad_result: Result<i32, i32> = Err(10);

// The `is_ok` and `is_err` methods do what they say.
assert!(good_result.is_ok() && !good_result.is_err());
assert!(bad_result.is_err() && !bad_result.is_ok());

// `map` consumes the `Result` and produces another.
let good_result: Result<i32, i32> = good_result.map(|i| i + 1);
let bad_result: Result<i32, i32> = bad_result.map(|i| i - 1);

// Use `and_then` to continue the computation.
let good_result: Result<bool, i32> = good_result.and_then(|i| Ok(i == 11));

// Use `or_else` to handle the error.
let bad_result: Result<i32, i32> = bad_result.or_else(|i| Ok(i + 20));

// Consume the result and return the contents with `unwrap`.
let final_awesome_result = good_result.unwrap();

Result必须被使用

编程中常见的问题就是忽略了返回值,从而没有办法应对异常情况。Result开启了#[must_use]属性,如果忽略了result值,编译器将会告警。因此,Result特别于可适用于可能能遇到错误的函数.

You might instead, if you don't want to handle the error, simply assert success with expect. This will panic if the write fails, providing a marginally useful message indicating why:

如果你不想处理错误值,可简单的断言函数返回成功,如果失败,则panic。

use std::fs::File;
 use std::io::prelude::*;  
let mut file = File::create("valuable_data.txt").unwrap(); 
file.write_all(b"important message").expect("failed to write message");

也可以这样写:

assert!(file.write_all(b"important message").is_ok());

或者把错误返回给调用者:

fn write_message() -> io::Result<()> {   
  let mut file = File::create("valuable_data.txt")?;    
  file.write_all(b"important message")?;     
  Ok(()) 
}

更简单的处理返回值:使用“?”操作符

如果你的代码有大量的函数调用会返回Result,那么错误处理将会是非常冗余枯燥的。Rust语言提供了?语法来简化错误值得传播。

原来的代码:

use std::fs::File;
use std::io::prelude::*;
use std::io;

struct Info {
    name: String,
    age: i32,
    rating: i32,
}

fn write_info(info: &Info) -> io::Result<()> {
    // Early return on error
    let mut file = match File::create("my_best_friends.txt") {
           Err(e) => return Err(e),
           Ok(f) => f,
    };
    if let Err(e) = file.write_all(format!("name: {}n", info.name).as_bytes()) {
        return Err(e)
    }
    if let Err(e) = file.write_all(format!("age: {}n", info.age).as_bytes()) {
        return Err(e)
    }
    if let Err(e) = file.write_all(format!("rating: {}n", info.rating).as_bytes()) {
        return Err(e)
    }
    Ok(())
}

使用?改写后的代码:

use std::fs::File;
use std::io::prelude::*;
use std::io;

struct Info {
    name: String,
    age: i32,
    rating: i32,
}

fn write_info(info: &Info) -> io::Result<()> {
    let mut file = File::create("my_best_friends.txt")?;
    // Early return on error
    file.write_all(format!("name: {}n", info.name).as_bytes())?;
    file.write_all(format!("age: {}n", info.age).as_bytes())?;
    file.write_all(format!("rating: {}n", info.rating).as_bytes())?;
    Ok(())
}

将?放置于Result后面,如果result是成功,则返回成功包含的值,程序继续执行;如果是失败,则返回Err。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值