Методы unwrap и expect типа Result

Последнее обновление: 04.05.2021

Для перехвата и обработки ошибки в прошлой теме применялась конструкция match:

fn main() {

	let tom_result = create_person("Tom", 36);
	let tom = match tom_result{
		Ok(person) => person,
		Err(err_message) => panic!("Возникла проблема: {}", err_message)
	};
	
	println!("Name: {}  Age: {}", tom.name, tom.age);
}

struct Person{ name: String, age:u8}

fn create_person(username: &str, userage: u8) -> Result<Person, String>{
	
	if userage < 110{
		let new_person = Person{name: String::from(username), age: userage };
		Result::Ok(new_person)
	}
	else { 
		Result::Err(String::from("Некорректный возраст. Возраст должен быть меньше 110")) 
	}
}

Причем само получение результата функции как бы разделяется на две части. Сначала получаем собственно результат функции - объект Result:

let tom_result = create_person("Tom", 36);

Затем применяем конструкцию match для получения объекта Person:

let tom = match tom_result{ ..... };

Такой способ может показаться слишком избыточым в плане кода. Нам надо определить слишком много действий, чтобы получить требуемый объект Person. Однако тип Result позволяет упростить работу, предоставляя специальные методы.

unwrap

Одним из таких методов является unwrap(). Если возвращенный объект Result представляет константу Ok, то метод unwrap() возвращает объект, который содержится в константе Ok. Но если объект Result представляет константу Err, то метод unwrap() вызывает макрос panic!.

Так, перепишем предыдущий пример с применением метода unwrap():

fn main() {

	let tom = create_person("Tom", 136).unwrap();
	println!("Name: {}  Age: {}", tom.name, tom.age);
}

struct Person{ name: String, age:u8}

fn create_person(username: &str, userage: u8) -> Result<Person, String>{
	
	if userage < 110{
		let new_person = Person{name: String::from(username), age: userage };
		Result::Ok(new_person)
	}
	else { 
		Result::Err(String::from("Некорректный возраст. Возраст должен быть меньше 110")) 
	}
}

Если объект Person будет успешно создан, то через переменную tom мы сможем использовать далее в программе.

В случае ошибки мы получим следующее сообщение:

Result и метод unwrap в Rust

expect

Метод expect() работает аналогично за тем исключением, что позволяет установить сообщение, которое будет передаваться в макрос panic:

fn main() {

	let tom = create_person("Tom", 36).expect("Что-то пошло не так....");
	println!("Name: {}  Age: {}", tom.name, tom.age);
}

struct Person{ name: String, age:u8}

fn create_person(username: &str, userage: u8) -> Result<Person, String>{
	
	if userage < 110{
		let new_person = Person{name: String::from(username), age: userage };
		Result::Ok(new_person)
	}
	else { 
		Result::Err(String::from("Некорректный возраст. Возраст должен быть меньше 110")) 
	}
}

unwrap_or_else

Еще одну возможность предоставляет метод unwrap_or_else(). Если возвращенный объект Result представляет константу Ok, то метод unwrap_or_else() возвращает объект, который содержится в константе Ok.

Но если объект Result представляет константу Err, то метод вызывает вызывает передаваемую в качестве параметра функцию. Эта функция в качестве параметра получает объект ошибки из константы Err и сама определяет логику обработки ошибки. Например:

fn main() {

	let tom = create_person("Tom", 136).unwrap_or_else(|error| {
	
		panic!("Возникла проблема: {}", error)
	});
	
	println!("Name: {}  Age: {}", tom.name, tom.age);
}

struct Person{ name: String, age:u8}

fn create_person(username: &str, userage: u8) -> Result<Person, String>{
	
	if userage < 110{
		let new_person = Person{name: String::from(username), age: userage };
		Result::Ok(new_person)
	}
	else { 
		Result::Err(String::from("Некорректный возраст. Возраст должен быть меньше 110")) 
	}
}

Здесь в метод unwrap_or_else() передается функция |error| { panic!("Возникла проблема: {}", error); }. Параметр error - это, что передается в константу Err - в данном случае объект String с сообщением об ошибке.

Помощь сайту
Юмани:
410011174743222
Перевод на карту
Номер карты:
4048415020898850