Introdução: por que isso é um problema?
\nSe você já escreveu algo em Rust mais complexo que "Hello, World!", certamente já se deparou com uma situação em que o compilador literalmente grita com você: "expected &'static str, but found String". Familiar? Esta é uma das perguntas mais populares no Stack Overflow (dezenas de milhares de visualizações), e não é à toa.
\nA questão é que String e &'static str são dois animais diferentes. String é um tipo proprietário que pode crescer e mudar durante a execução. Já &'static str é uma referência a uma fatia de string que vive durante todo o programa. É como comparar uma mala com coisas (String) com uma prateleira fixa permanentemente (&'static str).
Neste tutorial, abordaremos todas as formas legais de transformar String em &'static str, desde as simples até as avançadas. E sim, mostrarei como não dar um tiro no pé durante o processo.
O que é &'static str na prática?
\nAntes de sair codificando, vamos entender a teoria. &'static str é uma referência a uma string que tem a garantia de viver durante todo o tempo de execução do programa. Essas strings geralmente são embutidas diretamente no binário:
let hello: &'static str = "Hello, world!"; // Vive para sempre\n\nMas e se a string for criada dinamicamente? Por exemplo, lida de um arquivo ou recebida da rede? É aí que a coisa fica interessante.
\n\nMétodo nº1: O mais simples — vazamento de memória (sim, é legal)
\nIsso mesmo, você não ouviu errado. Rust tem um vazamento de memória intencional através da função Box::leak. Isso não é um bug, é uma funcionalidade! Você literalmente diz ao compilador: "Esqueça essa memória, ela é minha para sempre".
use std::boxed::Box;\n\nfn string_to_static_str(s: String) -> &'static str {\n // Transforma String em Box<str>, depois "esquece" dela\n let boxed_str: Box<str> = s.into_boxed_str();\n // Agora essa string viverá para sempre\n Box::leak(boxed_str)\n}\n\nfn main() {\n let dynamic_string = String::from("Nasci dinamicamente!");\n let static_ref: &'static str = string_to_static_str(dynamic_string);\n println!("{}", static_ref);\n // A memória nunca mais será liberada\n}\n\nVantagens: Simples, eficiente, não requer crates externos.
\nDesvantagens: Você perde o controle sobre a memória para sempre. Se chamar isso em um loop — olá, OOM (Out of Memory).
Quando isso é apropriado?
\n- \n
- Quando você sabe exatamente que a string é necessária durante toda a vida do programa (por exemplo, configuração carregada uma vez na inicialização). \n
- Em sistemas embarcados, onde não há heap e tudo é estático. \n
Método nº2: Lazy Static — para preguiçosos e inteligentes
\nA crate lazy_static é um clássico do Rust. Ela permite criar uma variável estática que é inicializada apenas na primeira vez que é acessada. Ideal para configurações e dados globais.
\n// Adicione em Cargo.toml: lazy_static = "1.4"\nuse lazy_static::lazy_static;\n\nlazy_static! {\n static ref MY_STRING: String = {\n // Suponha que estamos lendo uma string de um arquivo\n String::from("Carregado preguiçosamente!")\n };\n}\n\nfn get_static_str() -> &'static str {\n // lazy_static fornece automaticamente &'static str\n &MY_STRING\n}\n\nfn main() {\n println!("{}", get_static_str());\n}\n\nVantagens: \n
- \n
- Seguro (sem vazamento de memória). \n
- Inicialização preguiçosa — a string é criada apenas quando necessário. \n
- Funciona com qualquer tipo, não apenas com strings. \n
- \n
- Dependência de uma crate externa. \n
- Pode ser excessivo para casos simples. \n
Método nº3: OnceCell e OnceLock — alternativa moderna
\nA partir do Rust 1.70, na biblio