Introdução: por que o Rust não gosta de chaves?
\n\nSe você já escreveu em Rust e tentou exibir algo como { "name": "Rust" } usando println!, certamente viu isto:
println!("{ "name": "Rust" }"); // Erro de compilação!\n\nO compilador informa sarcasticamente: "invalid reference to argument 'name' — no argument named 'name' found". E você fica perplexo: como exibir chaves em uma string? Em Python, isso é feito com {{ }}, mas lá é mais simples. No Rust, a filosofia é diferente: chaves não são apenas símbolos, mas parte de um poderoso sistema de formatação, emprestado do Python, mas com nuances.
Neste artigo, abordaremos todas as formas de escapar chaves no Rust: desde o básico {{ }} até truques com Debug e raw string literals. Você aprenderá a exibir JSON, gerar código e trabalhar com templates sem cair em armadilhas do compilador.
Por que as chaves são especiais?
\n\nNo Rust, as macros format!, println!, write! e format_args! usam chaves como marcadores de substituição. Por exemplo:
let name = "Rust";\nprintln!("Hello, {}!", name); // Hello, Rust!\n\nAqui, {} é um placeholder que é substituído pelo valor da variável. Mas e se você precisar do próprio símbolo { ou }? O Rust usa um truque simples: duplicar as chaves.
Método 1: Duplicação clássica de {{ e }}
\n\nA maneira mais simples e óbvia é escrever duas chaves seguidas. O primeiro par {{ se transforma em uma {, e }} em uma }.
Exemplo 1: Escape simples
\nfn main() {\n let text = format!("Função main() {{ ... }}");\n println!("{}", text);\n // Saída: Função main() { ... }\n}\n\nExemplo 2: Escape com substituição
\nfn main() {\n let lang = "Rust";\n let year = 2015;\n let result = format!("{{ \\"lang\\": \\"{}\\", \\"year\\": {} }}", lang, year);\n println!("{}", result);\n // Saída: { "lang": "Rust", "year": 2015 }\n}\n\nEste método funciona em todos os lugares: em println!, write!, format!. Lembre-se da regra: duas chaves = uma chave.
Método 2: Argumentos nomeados e escape
\n\nSe você usa argumentos nomeados (por exemplo, {name}), o escape também funciona, mas é preciso ter cuidado com a posição das chaves.
Exemplo 3: Placeholders nomeados e chaves
\nfn main() {\n let user = "Alice";\n // Queremos exibir: Olá, {Alice}!\n println!("Olá, {{{}}}!", user);\n // Saída: Olá, {Alice}!\n}\n\nVamos analisar a string "Olá, {{{}}}!":\n
- \n
{{→ exibe{\n {}→ substitui poruser\n }}→ exibe}\n
Importante: o número de chaves é sempre par para o escape. Se você tiver {{{, é um erro, pois três chaves não formam um par correto.
Método 3: Uso do formato Debug ({:?})
\n\nÀs vezes, você quer exibir uma estrutura de dados de forma que ela apareça automaticamente com chaves. Por exemplo, ao depurar ou gerar JSON.
\n\nExemplo 4: Exibindo estrutura via Debug
\n#[derive(Debug)]\nstruct Point {\n x: i32,\n y: i32,\n}\n\nfn main() {\n let p = Point { x: 10, y: 20 };\n println!("{:?}", p);\n // Saída: Point { x: 10, y: 20 }\n}\n\nA trait Debug adiciona automaticamente chaves ao redor dos campos. Isso é útil quando você precisa mostrar rapidamente o estado de um objeto. Mas se você precisa exatamente de JSON ou ou