iniciante25 minutosLição 3 de 10

Variáveis e Mutabilidade

Entenda a nomenclatura de variáveis em Rust, shadowing, constantes e como a imutabilidade previne classes inteiras de bugs

Variáveis e Mutabilidade

Variáveis em Rust são imutáveis por padrão. Esta é uma das decisões centrais de design da linguagem — ela leva você a um código mais seguro e previsível.

Variáveis Imutáveis

rust
fn main() { let x = 5; // x = 6; // ERRO: cannot assign twice to immutable variable println!("x é {x}"); }
ℹ️Note

Imutabilidade por padrão remove uma categoria inteira de bugs: mutação não intencional. Se um valor não precisa mudar, o compilador o impõe.

Variáveis Mutáveis

Use mut para tornar uma variável mutável:

rust
fn main() { let mut y = 10; println!("y é {y}"); y = 15; println!("agora y é {y}"); }
DeclaraçãoPode Reatribuir?Pode Modificar?Caso de Uso
let x = 5;NãoNãoConstantes, dados somente leitura
let mut x = 5;SimSimContadores, acumuladores, estado

Constantes

Constantes são sempre imutáveis, devem ter anotações de tipo explícitas, e podem ser declaradas em qualquer escopo (incluindo global):

rust
const VELOCIDADE_MAXIMA: u32 = 120; // Anotação de tipo obrigatória const NOME_APP: &str = "MeuApp"; fn main() { println!("{NOME_APP} velocidade máxima: {VELOCIDADE_MAXIMA}"); }
Característicaletconst
Mutável?Apenas com mutNunca
Anotação de tipoOpcionalObrigatória
EscopoBlocoQualquer escopo (incluindo global)
Computada emExecuçãoTempo de compilação
Inline?NãoSim (valor copiado em cada uso)
rust
const TRES_HORAS_EM_SEGUNDOS: u32 = 60 * 60 * 3; // Expressão em tempo de compilação
⚠️Warning

Valores const são inseridos inline em cada ponto de uso. Isso significa que se você usar uma const em muitos lugares, ela é duplicada. Para um único local de memória, use static.

Shadowing

Rust permite sombreado (shadowing) de uma variável ao redeclará-la com let:

rust
fn main() { let x = 5; let x = x + 1; // Shadow: nova variável, novo tipo possível let x = x * 2; println!("x é {x}"); // 12 // Shadowing permite mudar o tipo let espacos = " "; let espacos = espacos.len(); // Agora espacos é um número }

Shadowing vs Mutabilidade

Aspectolet mut xlet x (shadowing)
Muda valorSimSim (nova variável)
Muda tipoNãoSim
Local de memóriaMesmoNovo
EscopoMesmo blocoAntiga ligação sombreada
rust
fn main() { // Mutabilidade: mesmo tipo, mesma memória let mut contador = 0; contador += 1; contador += 1; println!("{contador}"); // 2 // Shadowing: nova variável, pode mudar tipo let valor = "olá"; let valor = valor.len(); println!("{valor}"); // 3 }
Success

Shadowing é útil para transformar valores mantendo o mesmo nome. Use quando precisar mudar o tipo ou quando o valor antigo não deve mais ser acessível.

Escopo de Variáveis

Variáveis existem apenas dentro do bloco em que são declaradas (geralmente {}):

rust
fn main() { let externa = 10; { let interna = 20; println!("interna: {interna}, externa: {externa}"); // Ambas acessíveis } // println!("{interna}"); // ERRO: não encontrada no escopo println!("externa: {externa}"); // Ainda acessível }

Inicialização de Variáveis

Variáveis devem ser inicializadas antes do uso:

rust
fn main() { let x: i32; // println!("{x}"); // ERRO: usada antes da inicialização x = 5; println!("{x}"); // OK }
⚠️Warning

Rust não permite usar uma variável não inicializada. Isso previne comportamento indefinido comum em C/C++ onde ler memória não inicializada produz valores lixo.

Convenções de Nomenclatura

ItemConvençãoExemplo
Variáveissnake_casenome_usuario, contagem_maxima
ConstantesSCREAMING_SNAKE_CASEVELOCIDADE_MAXIMA, CHAVE_API
Funçõessnake_casecalcular_area()
TiposPascalCasePerfilUsuario, String
rust
const TIMEOUT_PADRAO_MS: u64 = 5000; fn main() { let idade_usuario: u8 = 25; let ativo: bool = true; }

Padrões com Sublinhado

rust
fn main() { let _nao_usado = 42; // Suprime aviso de variável não usada let _ = 100; // Descarta completamente — sem vinculação let _x = 10; // Prefixo sublinhado = "intencionalmente não usado" }

Atribuição por Desestruturação

Rust suporta desestruturação com let:

rust
fn main() { let (x, y, z) = (1, 2, 3); println!("{x}, {y}, {z}"); // 1, 2, 3 // Sublinhado para descartar partes let (a, _, b) = (10, 20, 30); println!("{a}, {b}"); // 10, 30 }

Padrões do Mundo Real

rust
// Máquina de estados segura: estados enum imutáveis enum EstadoConexao { Desconectado, Conectando, Conectado, } fn main() { let estado = EstadoConexao::Desconectado; // estado = EstadoConexao::Conectado; // Deve usar 'mut' ou shadow let estado = EstadoConexao::Conectado; // Shadow: novo estado // Use shadowing para conversão de tipo let entrada = " Olá Mundo "; let entrada = entrada.trim(); // &str -> &str (aparado) let entrada = entrada.to_string(); // &str -> String let entrada = entrada.as_bytes(); // String -> &[u8] }

Perguntas de Prática

  1. Por que variáveis são imutáveis por padrão em Rust?
  2. Qual palavra-chave torna uma variável mutável?
  3. Qual a diferença entre const e let?
  4. O que o shadowing permite que mut não permite?
  5. Uma constante pode ser declarada dentro de uma função?
  6. O que acontece quando uma variável sai de escopo?
  7. Por que variáveis devem ser inicializadas antes do uso?
  8. Qual convenção de nomenclatura é usada para constantes Rust?
  9. Como suprimir um aviso de variável não usada?
  10. O que let (x, _, z) = (1, 2, 3); faz?
Progresso30%