Rust: Como comparar String com literais de string (match)

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Por que o Rust não permite simplesmente comparar String com "olá"?

\n\n

Se você está começando a aprender Rust e já se deparou com a necessidade de comparar uma variável do tipo String com algum literal de string como "hello" ou "world", provavelmente já viu um erro estranho do compilador. Você escreve algo como:

\n\n
let user_input = String::from("start");\nmatch user_input {\n    "start" => println!("Começando!"),\n    "stop"  => println!("Parando!"),\n    _       => println!("Comando desconhecido"),\n}\n
\n\n

E o compilador mostra algo como: "expected struct `String`, found `&str`". Familiar?

\n\n

No Stack Overflow, a pergunta "How to match a String against string literals?" tem milhares de visualizações — é uma verdadeira dor de cabeça para iniciantes. Neste artigo, vamos explicar por que isso acontece e mostrar três maneiras simples de resolver o problema. Você aprenderá como o sistema de propriedade e empréstimo do Rust funciona na prática e deixará de temer os erros do compilador.

\n\n

Natureza do conflito: String vs &str

\n\n

Para entender o problema, precisamos relembrar os fundamentos. Rust tem dois tipos principais para trabalhar com texto:

\n\n
    \n
  • String — é uma string proprietária, armazenada no heap. Ela pode ser modificada, crescer e diminuir. Exemplo: let s = String::from("hello");
  • \n
  • &str — é uma fatia de string. É uma referência a parte de uma string (ou a um literal de string, que fica armazenado diretamente no binário do programa). Exemplo: "hello" é exatamente &'static str.
  • \n
\n\n

Quando você escreve match user_input { "start" => ... }, está tentando comparar String com &str. O compilador diz: "Não sei como compará-los diretamente, os tipos são diferentes!". E isso é bom — o Rust protege você de conversões implícitas que poderiam causar perda de desempenho ou bugs ocultos.

\n\n

Mas como resolver? Existem três soluções simples e elegantes.

\n\n

Solução 1: Empréstimo com as_str()

\n\n

A maneira mais direta e compreensível é obter uma fatia de string (&str) a partir de String usando o método as_str(). Este método retorna uma referência ao conteúdo da string, sem copiá-la. Fica assim:

\n\n
fn main() {\n    let command = String::from("start");\n\n    match command.as_str() {\n        "start" => println!("Iniciando sistema..."),\n        "stop"  => println!("Parando..."),\n        "pause" => println!("Pausando..."),\n        _       => println!("Comando desconhecido: {}", command),\n    }\n}\n
\n\n

Por que funciona? as_str() retorna um &str, que agora pode ser comparado com literais. O Rust vê que ambos os operandos são &str, e a correspondência de padrões funciona perfeitamente.

\n\n

Vantagens: simplicidade, legibilidade, custo zero (empréstimo, não cópia).

\n\n

Desvantagens: é preciso lembrar de chamar o método. Mas é um detalhe menor.

\n\n

Solução 2: Comparação em condição if

\n\n

Se você não precisa de todo o poder do match, pode usar if comuns com o método eq() ou o operador ==. O Rust consegue comparar String e &str através da trait PartialEq, que é implementada para esse par de tipos.

\n\n
fn main() {\n    let user_input = String::from("admin");\n\n    if user_input == "admin" {\n        println!("Acesso permitido!");\n    } else if user_input == "guest" {\n        println!("Acesso de convidado");\n    } else {\n        println!("Login inválido");\n    }\n}\n
\n\n

Isso funciona porque o compilador converte automaticamente String para &str durante a comparação. Mas no match essa conversão não ocorre — lá é necessário uma correspondência exata de tipos.

Blogs

Book Recommendations