O Operador de Interrogação '?'
Parte da seção Logic & Flow do Journey de Rust da Coddy — lição 46 de 66.
Ao trabalhar com funções que retornam Result, você frequentemente precisa lidar com erros, seja tratando-os localmente ou passando-os para a função chamadora. Rust fornece um operador elegante para este padrão comum: o operador de ponto de interrogação ?.
O operador ? fornece uma maneira limpa de propagar erros sem escrever instruções match verbosas. Quando você coloca ? após um Result, ele desempacota automaticamente um valor Ok ou retorna imediatamente da função atual com o Err:
fn parse_and_double(s: &str) -> Result<i32, std::num::ParseIntError> {
let number = s.parse::<i32>()?; // Se a análise falhar, retorna o erro
Ok(number * 2) // Se for bem-sucedido, dobra o número
}Isso é equivalente a escrever uma instrução match completa, mas muito mais concisa. Se s.parse::<i32>() retornar um Ok, o ? extrai o valor e o atribui a number. Se ele retornar um Err, o ? retorna imediatamente esse erro de toda a função.
O operador ? só pode ser usado em funções que retornam um Result (ou Option), já que ele precisa ser capaz de retornar um erro.
Desafio
FácilVocê receberá duas entradas. A primeira entrada é uma string que deve ser convertida em um número inteiro, e a segunda entrada é outra string que também deve ser convertida em um número inteiro. Crie uma função chamada add_numbers que recebe dois slices de string como parâmetros e retorna um Result<i32, std::num::ParseIntError>. Dentro da função, use o operador ? para converter ambas as strings e retornar a soma delas envolvida em Ok. Chame a função com as duas entradas e trate o resultado usando match.
Requisitos:
- Leia a primeira entrada (primeiro número como string) e remova os espaços em branco
- Leia a segunda entrada (segundo número como string) e remova os espaços em branco
- Crie uma função
add_numbersque recebe dois parâmetros&stre retornaResult<i32, std::num::ParseIntError> - Dentro da função, converta a primeira string para
i32usando o operador? - Converta a segunda string para
i32usando o operador? - Retorne
Ok(sum)onde sum é a soma de ambos os números convertidos - Chame a função com as duas strings de entrada
- Use uma expressão
matchpara tratar oResult - No braço
Ok(value), imprima:Sum: [value] - No braço
Err(_), imprima:Parsing error
Entrada:
- Primeira linha: Uma string representando um número (ex:
15) - Segunda linha: Uma string representando outro número (ex:
27)
Saída:
- Se ambas as strings forem números válidos:
Sum: [result] - Se qualquer uma das strings não puder ser convertida:
Parsing error
Folha de consulta
O operador de ponto de interrogação ? fornece uma maneira concisa de propagar erros em funções que retornam Result.
Quando colocado após um Result, o operador ?:
- Desembrulha um valor
Oke continua a execução - Retorna imediatamente um
Errda função atual se ocorrer um erro
fn parse_and_double(s: &str) -> Result<i32, std::num::ParseIntError> {
let number = s.parse::<i32>()?; // Se a análise falhar, retorna o erro
Ok(number * 2) // Se for bem-sucedido, dobra o número
}O operador ? só pode ser usado em funções que retornam um tipo Result ou Option.
Experimente você mesmo
use std::io;
// TODO: Crie a função add_numbers aqui
// Ela deve receber dois parâmetros &str e retornar Result<i32, std::num::ParseIntError>
fn main() {
// Lê a primeira entrada
let mut input1 = String::new();
io::stdin().read_line(&mut input1).expect("Failed to read line");
let input1 = input1.trim();
// Lê a segunda entrada
let mut input2 = String::new();
io::stdin().read_line(&mut input2).expect("Failed to read line");
let input2 = input2.trim();
// TODO: Chame add_numbers com input1 e input2
// TODO: Use match para tratar o Result
// Imprima "Sum: [value]" para Ok(value)
// Imprima "Parsing error" para Err(_)
}Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.
Todas as lições de Logic & Flow
1Fluxo de Controle Avançado
A Expressão 'match'Correspondência de Múltiplos ValoresCorrespondência de IntervalosA Expressão 'if let'Loops como ExpressõesRecapitulação - Parser de Comandos Simples4Agrupando Dados com Structs
O que é uma Struct?Visão Geral de StructsAcessando Campos de uma StructStructs MutáveisStructs como Parâmetros de FunçãoTuple StructsRecapitulação - Criando uma Struct Book7Tratando Erros com 'Result'
O que é um 'Result'?Usando 'match' com 'Result'is_ok() e is_err()Atalhos: unwrap e expectO Operador de Interrogação '?'Parsing de Strings para NúmerosRecapitulação - Função de Divisão Segura2Introdução a Vetores
O que é um Vetor?Criando um VetorAdicionando Elementos com pushAcessando Elementos do VetorIterando sobre um VetorIteração MutávelRemovendo ElementosRecapitulação - Rastreador de Pontuação Básico5Pares Chave-Valor com Hash Maps
O que é um Hash Map?Criando um Hash MapInserindo Pares Chave-ValorAcessando ValoresIterando sobre um Hash MapAtualizando um ValorRemovendo um ParRecapitulação - Contador de Palavras8Projeto: Inventário Simples de Itens
Configuração do ProjetoAdicionando um ItemVerificando o EstoqueVendendo um ItemJuntando tudo3Lista de Tarefas via Linha de Comando
Configuração do ProjetoAdicionando uma TarefaVisualizando Todas as TarefasRemovendo uma TarefaCódigo Final