<h2>String vs &str em Rust: Entendendo as Duas Formas de Texto</h2>
<h3>O que são String e &str?</h3>
<p>Em Rust, temos duas formas principais de representar texto: <code>String</code> e <code>&str</code>. A diferença fundamental está em como a memória é gerenciada e onde os dados são armazenados. <code>String</code> é um tipo alocado dinamicamente no heap, você é responsável por seu gerenciamento, enquanto <code>&str</code> é uma referência a uma sequência de bytes UTF-8 válida, geralmente alocada na stack ou na seção de dados do binário.</p>
<p>Pense em <code>String</code> como um vetor de caracteres que você pode modificar livremente — tem capacidade, comprimento e proprietário. Já <code>&str</code> é uma visão imutável sobre esses dados: um "empréstimo" que aponta para um local de memória sem poder alterar o conteúdo. Essa distinção é central na filosofia de segurança de memória do Rust.</p>
<pre><code class="language-rust">fn main() {
// String: alocado no heap, mutável, proprietário
let mut s1 = String::from("Olá");
s1.push_str(", Mundo!");
println!("{}", s1); // "Olá, Mundo!"
// &str: referência imutável, literais são na stack/binário
let s2: &str = "Olá, Rust!";
println!("{}", s2); // "Olá, Rust!"
// &str pode vir de uma String
let s3 = String::from("Teste");
let referencia: &str = &s3;
println!("{}", referencia); // "Teste"
}</code></pre>
<h3>Diferenças de Performance e Memória</h3>
<p><code>String</code> consome mais memória porque armazena três informações no stack: um ponteiro para os dados no heap, a capacidade e o comprimento atual. A cada alocação, pode haver fragmentação de memória. <code>&str</code>, por sua vez, é apenas um ponteiro (64 bits) e um comprimento (64 bits) — 16 bytes no total em arquiteturas de 64 bits — tornando-a muito mais leve para passar entre funções.</p>
<p>Quando você trabalha com strings literais como <code>"Olá"</code>, o compilador as coloca como dados imutáveis no binário (seção <code>.rodata</code>), e <code>&str</code> simplesmente aponta para lá. Não há alocação dinâmica. Use <code>&str</code> como padrão em parâmetros de funções; use <code>String</code> apenas quando você realmente precisa possuir e modificar o texto.</p>
<pre><code class="language-rust">// Não faça isto (ineficiente):
fn processar_texto(texto: String) {
println!("{}", texto);
}
// Faça isto:
fn processar_texto(texto: &str) {
println!("{}", texto);
}
fn main() {
let s = String::from("Dados importantes");
processar_texto(&s); // passa &str, não String
processar_texto("Literal direto"); // funciona naturalmente
}</code></pre>
<h3>Conversão e Coerção</h3>
<p>Rust permite coerção automática de <code>String</code> para <code>&str</code> em muitos contextos. Quando você passa uma <code>String</code> para uma função que espera <code>&str</code>, o compilador automaticamente converte. Isso é uma das características mais úteis da linguagem — você possui uma <code>String</code>, mas empresta apenas uma visão quando necessário.</p>
<p>Para converter explicitamente, use <code>&string[..]</code> ou <code>&string</code> (quando esperado <code>&str</code>). Para ir na direção oposta, de <code>&str</code> para <code>String</code>, use <code>String::from()</code>, <code>.to_string()</code> ou <code>.to_owned()</code>. Entender essas conversões é crucial para não lutar contra o borrow checker do Rust.</p>
<pre><code class="language-rust">fn saudacao(nome: &str) -> String {
format!("Olá, {}!", nome)
}
fn main() {
// Coerção automática: String vira &str
let nome = String::from("Alice");
let msg = saudacao(&nome); // &nome é &str
// Conversão explícita
let slice: &str = &nome[0..5]; // "&str" a partir de parte de String
println!("{}", slice); // "Alice"
// &str para String
let literai: &str = "Bob";
let proprietario: String = literai.to_string();
println!("{}", proprietario); // "Bob"
}</code></pre>
<h3>Quando Usar Cada Uma</h3>
<p>Use <code>&str</code> em assinaturas de funções como argumento padrão — é ergonômico e eficiente. Use <code>String</code> quando você precisa possuir, modificar ou construir texto dinamicamente, como em loops que concatenam dados ou ao ler de entrada do usuário. Em estruturas de dados, <code>String</code> é a escolha padrão quando você precisa armazenar texto; <code>&str</code> é usada para referências que vivem enquanto seus dados subjacentes existem.</p>
<p>Não tenha medo de ter <code>String</code> em suas estruturas. A cláusula de tempo de vida em <code>&str</code> frequentemente torna o código mais complexo sem benefício real. Reserve <code>&str</code> para quando realmente está apenas emprestando texto, não para quando é responsável por sua existência.</p>
<pre><code class="language-rust">#[derive(Debug)]
struct Pessoa {
nome: String, // proprietária dos dados
email: String,
}
impl Pessoa {
fn new(nome: &str, email: &str) -> Self {
Pessoa {
nome: nome.to_string(),
email: email.to_string(),
}
}
fn apresentar(&self) -> String {
format!("Sou {} ({})", self.nome, self.email)
}
}
fn main() {
let pessoa = Pessoa::new("Carlos", "carlos@email.com");
println!("{}", pessoa.apresentar());
}</code></pre>
<h2>Conclusão</h2>
<p>Os três pontos essenciais: <strong>primeiro</strong>, <code>String</code> é alocado dinamicamente e mutável, enquanto <code>&str</code> é uma referência imutável e leve; <strong>segundo</strong>, a coerção automática permite passar <code>String</code> onde <code>&str</code> é esperado, facilitando a vida; <strong>terceiro</strong>, use <code>&str</code> em parâmetros de funções e <code>String</code> em propriedades de estruturas e quando você controla o ciclo de vida do dado.</p>
<p>Dominar essa distinção é fundamental em Rust. Investir tempo compreendendo <code>String</code> vs <code>&str</code> elimina frustrações futuras com o borrow checker e resulta em código mais eficiente.</p>
<h2>Referências</h2>
<ul>
<li><a href="https://doc.rust-lang.org/book/ch08-02-strings.html" target="_blank" rel="noopener noreferrer">The Rust Book - String Type</a></li>
<li><a href="https://doc.rust-lang.org/rust-by-example/std/str.html" target="_blank" rel="noopener noreferrer">Rust by Example - Strings</a></li>
<li><a href="https://doc.rust-lang.org/reference/types/textual.html" target="_blank" rel="noopener noreferrer">Rust Reference - String</a></li>
<li><a href="https://github.com/rust-lang/rustlings" target="_blank" rel="noopener noreferrer">Rustlings - Move Semantics (Relevant to ownership)</a></li>
<li><a href="https://www.oreilly.com/library/view/programming-rust-2nd/9781492052586/" target="_blank" rel="noopener noreferrer">Programming Rust: Fast and Safe Systems Development (2nd Ed.) - Jim Blandy, Jason Orendorff</a></li>
</ul>