Principais erros de desenvolvedores Rust iniciantes: como evitá-los

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

Introdução

Rust é uma poderosa linguagem de programação de sistemas que está ganhando popularidade devido à sua segurança e desempenho. No entanto, seu sistema de ownership (propriedade) e borrowing (empréstimo) frequentemente confunde iniciantes. Neste artigo, vamos analisar os principais erros de desenvolvedores Rust iniciantes para que você possa evitá-los e se familiarizar mais rapidamente com a linguagem. Abordaremos problemas típicos com borrowing, lifetimes (tempo de vida), strings e gerenciamento de memória.

1. Ignorar as regras de borrowing (Borrow Checker)

O erro mais comum é tentar ter simultaneamente uma referência mutável e uma imutável para os mesmos dados. Rust proíbe estritamente isso em tempo de compilação.

Problema: múltiplas referências

fn main() {
    let mut data = vec![1, 2, 3];
    let ref1 = &data; // referência imutável
    let ref2 = &mut data; // referência mutável — ERRO!
    println!("{} {}", ref1[0], ref2[0]);
}

O compilador emitirá um erro: cannot borrow `data` as mutable because it is also borrowed as immutable.

Solução: escopo correto

fn main() {
    let mut data = vec![1, 2, 3];
    {
        let ref1 = &data; // referência imutável
        println!("{}", ref1[0]);
    } // ref1 sai de escopo
    let ref2 = &mut data; // agora é possível
    ref2[0] = 10;
    println!("{}", ref2[0]);
}

Sempre monitore o tempo de vida das referências. Se precisar trabalhar com referências mutáveis e imutáveis, separe-as em blocos diferentes.

2. Trabalho incorreto com strings: String vs &str

Iniciantes frequentemente confundem String (tipo proprietário, mutável) e &str (referência a uma fatia de string). Isso leva a erros ao passar strings para funções.

Problema: esperar ownership em vez de referência

fn print_length(s: String) {
    println!("Comprimento: {}", s.len());
}

fn main() {
    let name = "Alice".to_string();
    print_length(name);
    println!("Nome: {}", name); // ERRO! name foi movida
}

Solução: use &str para parâmetros

fn print_length(s: &str) {
    println!("Comprimento: {}", s.len());
}

fn main() {
    let name = "Alice".to_string();
    print_length(&name); // passamos uma referência
    println!("Nome: {}", name); // agora funciona
}

Regra: se a função não precisa assumir a propriedade, use &str. Isso torna o código flexível — você pode passar tanto &String quanto literais de string "texto".

3. Erros com lifetimes (Tempo de Vida)

Quando uma função retorna uma referência, Rust exige que você especifique por quanto tempo essa referência viverá. Iniciantes frequentemente esquecem as anotações de lifetime.

Problema: lifetimes implícitos

fn longest(x: &str, y: &str) -> &str { // ERRO: missing lifetime specifier
    if x.len() > y.len() { x } else { y }
}

Solução: adicione um lifetime comum

fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() { x } else { y }
}

fn main() {
    let s1 = String::from("curto");
    let s2 = "string longa";
    let result = longest(&s1, &s2);
    println!("A mais longa: {}", result);
}

A anotação 'a informa ao compilador que a referência retornada viverá no máximo tanto quanto o parâmetro de entrada mais curto. Isso garante segurança de memória.

4. Ignorar Option e Result

Rust não possui null. Em vez disso, usa Option<T> para possível ausência de valor e Result<T, E> para tratamento de erros. Iniciantes frequentemente tentam desreferenciar Option sem verificação.

Problema: pânico com unwrap

fn find_user(id: u32) -> Option<String> {
    if id == 1 {
        Some("Ana".to_string())
    }                

Blogs

Book Recommendations