खोज…


परिचय

निष्पादन के दौरान पुनर्प्राप्त करने योग्य त्रुटियों को इंगित करने के लिए जंग Result<T, E> मूल्यों का उपयोग करता है। अप्राप्य त्रुटियों का कारण घबरा जिसका खुद का एक विषय है।

टिप्पणियों

त्रुटि से निपटने का विवरण जंग प्रोग्रामिंग भाषा (उर्फ द बुक) में वर्णित है

सामान्य परिणाम के तरीके

use std::io::{Read, Result as IoResult};
use std::fs::File;

struct Config(u8);

fn read_config() -> IoResult<String> {
    let mut s = String::new();
    let mut file = File::open(&get_local_config_path())
        // or_else closure is invoked if Result is Err.
        .or_else(|_| File::open(&get_global_config_path()))?;
    // Note: In `or_else`, the closure should return a Result with a matching
    //       Ok type, whereas in `and_then`, the returned Result should have a
    //       matching Err type.
    let _ = file.read_to_string(&mut s)?;
    Ok(s)
}

struct ParseError;

fn parse_config(conf_str: String) -> Result<Config, ParseError> {
    // Parse the config string...
    if conf_str.starts_with("bananas") {
        Err(ParseError)
    } else {
        Ok(Config(42))
    }
}

fn run() -> Result<(), String> {
    // Note: The error type of this function is String. We use map_err below to
    //       make the error values into String type
    let conf_str = read_config()
        .map_err(|e| format!("Failed to read config file: {}", e))?;
    // Note: Instead of using `?` above, we can use `and_then` to wrap the let
    //       expression below.
    let conf_val = parse_config(conf_str)
        .map(|Config(v)| v / 2) // map can be used to map just the Ok value
        .map_err(|_| "Failed to parse the config string!".to_string())?;

    // Run...

    Ok(())
}

fn main() {
    match run() {
        Ok(_) => println!("Bye!"),
        Err(e) => println!("Error: {}", e),
    }
}

fn get_local_config_path() -> String {
    let user_config_prefix = "/home/user/.config";
    // code to get the user config directory
    format!("{}/my_app.rc", user_config_prefix)
}

fn get_global_config_path() -> String {
    let global_config_prefix = "/etc";
    // code to get the global config directory
    format!("{}/my_app.rc", global_config_prefix)
}

यदि कॉन्फ़िगरेशन फ़ाइलें मौजूद नहीं हैं, तो यह आउटपुट:

Error: Failed to read config file: No such file or directory (os error 2)

यदि पार्सिंग विफल रहा, तो यह आउटपुट:

Error: Failed to parse the config string!

नोट: जैसे-जैसे परियोजना बढ़ती है, त्रुटियों के मूल और प्रसार मार्ग के बारे में जानकारी खोए बिना इन बुनियादी तरीकों ( डॉक्स ) के साथ त्रुटियों को संभालने के लिए बोझिल हो जाएगा। इसके अलावा, यह निश्चित रूप से कई त्रुटियों के प्रकार को संभालने के लिए समय से पहले स्ट्रिंग में त्रुटियों को परिवर्तित करने के लिए एक बुरा अभ्यास है जैसा कि ऊपर दिखाया गया है। एक बेहतर तरीका टोकरा error-chain का उपयोग करना है।

कस्टम त्रुटि प्रकार

use std::error::Error;
use std::fmt;
use std::convert::From;
use std::io::Error as IoError;
use std::str::Utf8Error;

#[derive(Debug)] // Allow the use of "{:?}" format specifier
enum CustomError {
    Io(IoError),
    Utf8(Utf8Error),
    Other,
}

// Allow the use of "{}" format specifier
impl fmt::Display for CustomError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            CustomError::Io(ref cause) => write!(f, "I/O Error: {}", cause),
            CustomError::Utf8(ref cause) => write!(f, "UTF-8 Error: {}", cause),
            CustomError::Other => write!(f, "Unknown error!"),
        }
    }
}

// Allow this type to be treated like an error
impl Error for CustomError {
    fn description(&self) -> &str {
        match *self {
            CustomError::Io(ref cause) => cause.description(),
            CustomError::Utf8(ref cause) => cause.description(),
            CustomError::Other => "Unknown error!",
        }
    }

    fn cause(&self) -> Option<&Error> {
        match *self {
            CustomError::Io(ref cause) => Some(cause),
            CustomError::Utf8(ref cause) => Some(cause),
            CustomError::Other => None,
        }
    }
}

// Support converting system errors into our custom error.
// This trait is used in `try!`.
impl From<IoError> for CustomError {
    fn from(cause: IoError) -> CustomError {
        CustomError::Io(cause)
    }
}
impl From<Utf8Error> for CustomError {
    fn from(cause: Utf8Error) -> CustomError {
        CustomError::Utf8(cause)
    }
}

कारणों के माध्यम से Iterating

किसी त्रुटि के मूल कारण को खोजने के लिए डिबगिंग उद्देश्यों के लिए यह अक्सर उपयोगी होता है। त्रुटि मान की जांच करने के लिए, जो std::error::Error : को लागू std::error::Error

use std::error::Error;

let orig_error = call_returning_error();

// Use an Option<&Error>. This is the return type of Error.cause().
let mut err = Some(&orig_error as &Error);

// Print each error's cause until the cause is None.
while let Some(e) = err {
    println!("{}", e);
    err = e.cause();
}

बुनियादी त्रुटि रिपोर्टिंग और हैंडलिंग

Result<T, E> एक enum प्रकार है जिसके दो प्रकार हैं: Ok(T) टाइप T सार्थक परिणाम के साथ सफल निष्पादन, और Err(E) निष्पादन के दौरान एक अप्रत्याशित त्रुटि की घटना को दर्शाता है, टाइप E मान से वर्णित है ।

enum DateError {
    InvalidDay,
    InvalidMonth,
}

struct Date {
    day: u8,
    month: u8,
    year: i16,
}

fn validate(date: &Date) -> Result<(), DateError> {
    if date.month < 1 || date.month > 12 {
        Err(DateError::InvalidMonth)
    } else if date.day < 1 || date.day > 31 {
        Err(DateError::InvalidDay)
    } else {
        Ok(())
    }
}

fn add_days(date: Date, days: i32) -> Result<Date, DateError> {
    validate(&date)?; // notice `?` -- returns early on error
    // the date logic ...
    Ok(date)
}

अधिक विवरण के लिए डॉक्स भी देखें ? ऑपरेटर।

मानक लाइब्रेरी में एक Error विशेषता होती है जिसे लागू करने के लिए सभी त्रुटि प्रकारों की सिफारिश की जाती है। एक उदाहरण कार्यान्वयन नीचे दिया गया है।

use std::error::Error;
use std::fmt;

#[derive(Debug)]
enum DateError {
    InvalidDay(u8),
    InvalidMonth(u8),
}

impl fmt::Display for DateError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &DateError::InvalidDay(day) => write!(f, "Day {} is outside range!", day),
            &DateError::InvalidMonth(month) => write!(f, "Month {} is outside range!", month),
        }
    }
}

impl Error for DateError {
    fn description(&self) -> &str {
        match self {
            &DateError::InvalidDay(_) => "Day is outside range!",
            &DateError::InvalidMonth(_) => "Month is outside range!",
        }
    }

    // cause method returns None by default
}

नोट: आम तौर पर, Option<T> उपयोग रिपोर्टिंग त्रुटियों के लिए नहीं किया जाना चाहिए। Option<T> मूल्य के गैर-अस्तित्व की एक संभावित संभावना और इसके लिए एक सीधा कारण इंगित करता है। इसके विपरीत, Result<T, E> का उपयोग निष्पादन के दौरान अप्रत्याशित त्रुटियों की रिपोर्ट करने के लिए किया जाता है, और विशेष रूप से तब जब उनके बीच अंतर करने में विफलताओं के कई तरीके होते हैं। इसके अलावा, Result<T, E> का उपयोग केवल रिटर्न मान के रूप में किया जाता है। ( एक पुरानी चर्चा। )



Modified text is an extract of the original Stack Overflow Documentation
के तहत लाइसेंस प्राप्त है CC BY-SA 3.0
से संबद्ध नहीं है Stack Overflow