# Ownership e Borrowing em Rust: Guia Completo para Entrevistas Tecnicas > Domine os conceitos de ownership, borrowing e lifetimes em Rust. Guia pratico com exemplos de codigo para se preparar para entrevistas tecnicas de programacao de sistemas. - Published: 2026-03-31 - Updated: 2026-03-31 - Author: Anthony Fillion-Maillet - Tags: rust, ownership, borrowing, memory-management, systems-programming - Reading time: 10 min --- O sistema de ownership de Rust representa uma das inovacoes mais significativas no design de linguagens de programacao das ultimas decadas. Ao contrario de linguagens com garbage collector, Rust garante seguranca de memoria em tempo de compilacao, sem nenhum custo em tempo de execucao. Para desenvolvedores que se preparam para entrevistas tecnicas, compreender profundamente ownership e borrowing nao e apenas desejavel -- e essencial. Este guia aborda os pilares do modelo de memoria de Rust: move semantics, borrowing imutavel e mutavel, lifetimes e padroes praticos que aparecem frequentemente em entrevistas tecnicas. > **Por que ownership importa em entrevistas** > > Empresas que utilizam Rust -- como Mozilla, Cloudflare, Discord e Dropbox -- frequentemente avaliam candidatos sobre ownership e borrowing. Dominar esses conceitos demonstra compreensao solida de gerenciamento de memoria e programacao de sistemas. ## Move Semantics: Substituindo o Garbage Collector Em Rust, cada valor possui exatamente um proprietario (owner). Quando um valor e atribuido a outra variavel, a ownership e transferida -- este processo e chamado de **move**. Apos o move, a variavel original nao pode mais ser utilizada. Esse modelo elimina a necessidade de um garbage collector. O compilador sabe exatamente quando cada valor deve ser liberado da memoria: no momento em que seu proprietario sai do escopo. ```rust // move_semantics.rs fn main() { let original = String::from("interview prep"); let moved = original; // ownership transfers here // println!("{}", original); // compile error: value moved println!("{}", moved); // works fine } ``` No exemplo acima, `original` perde a ownership da String quando ela e atribuida a `moved`. Tentar utilizar `original` apos essa atribuicao resulta em um erro de compilacao. Isso previne acessos a memoria ja liberada (use-after-free), um dos bugs mais comuns em linguagens como C e C++. Para tipos primitivos que implementam a trait `Copy` (como `i32`, `f64`, `bool`), a atribuicao cria uma copia em vez de realizar um move. Para tipos mais complexos, e possivel utilizar o metodo `clone()` para criar uma copia explicita. ```rust // copy_vs_move.rs fn main() { let x: i32 = 42; let y = x; // copy, not move -- i32 is Copy println!("x = {}, y = {}", x, y); // both valid let s1 = String::from("hello"); let s2 = s1.clone(); // explicit deep copy println!("s1 = {}, s2 = {}", s1, s2); // both valid after clone } ``` A distincao entre `Copy` e `Clone` e um topico recorrente em entrevistas. Tipos `Copy` sao copiados implicitamente na stack, enquanto `Clone` exige uma chamada explicita e pode envolver alocacao no heap. ## Borrowing Imutavel: Emprestando sem Transferir Na maioria das situacoes, nao e necessario transferir a ownership de um valor. Rust permite **emprestar** (borrow) referencias a valores, sem transferir sua propriedade. Uma referencia imutavel (`&T`) permite leitura, mas nao modificacao. ```rust // immutable_borrowing.rs fn calculate_length(s: &String) -> usize { s.len() // read access through the reference } // s goes out of scope, but doesn't drop the String (not the owner) fn main() { let greeting = String::from("hello, Rust"); let len = calculate_length(&greeting); // borrow, don't move println!("'{}' has {} characters", greeting, len); // greeting still valid } ``` O operador `&` cria uma referencia imutavel. A funcao `calculate_length` recebe um emprestimo da String sem assumir sua ownership. Apos o retorno da funcao, `greeting` continua valida e utilizavel. Rust permite multiplas referencias imutaveis simultaneas ao mesmo valor. Isso e seguro porque nenhuma delas pode modificar o dado subjacente. ## Referencias Mutaveis e a Regra de Exclusividade Quando e necessario modificar um valor emprestado, utiliza-se uma referencia mutavel (`&mut T`). Porem, Rust impoe uma regra fundamental: **apenas uma referencia mutavel pode existir por vez**, e nao pode coexistir com referencias imutaveis ativas. ```rust // mutable_borrowing.rs fn append_greeting(s: &mut String) { s.push_str(", welcome to Rust!"); // modify through mutable ref } fn main() { let mut message = String::from("Hello"); append_greeting(&mut message); println!("{}", message); // "Hello, welcome to Rust!" } ``` A regra de exclusividade previne data races em tempo de compilacao. Se o compilador permitisse duas referencias mutaveis simultaneas, seria possivel ter leituras e escritas concorrentes ao mesmo dado, causando comportamento indefinido. ```rust // exclusivity_rule.rs fn main() { let mut data = String::from("shared state"); let r1 = &mut data; // let r2 = &mut data; // compile error: second mutable borrow println!("{}", r1); // After r1's last usage, a new mutable borrow is allowed let r3 = &mut data; // this works -- non-lexical lifetimes r3.push_str(" updated"); println!("{}", r3); } ``` O conceito de **Non-Lexical Lifetimes (NLL)**, introduzido no Rust 2018, permite que o compilador determine com precisao quando uma referencia deixa de ser utilizada, em vez de considerar todo o escopo lexico. No exemplo acima, `r1` nao e mais usado apos o `println!`, entao `r3` pode ser criado sem conflito. ## Lifetimes: Garantindo a Validade das Referencias Lifetimes sao anotacoes que informam ao compilador por quanto tempo uma referencia deve permanecer valida. Na maioria dos casos, o compilador infere lifetimes automaticamente (lifetime elision). Porem, em situacoes mais complexas, anotacoes explicitas sao necessarias. O exemplo classico e uma funcao que retorna uma referencia derivada de seus parametros: ```rust // lifetime_annotation.rs fn longest<'a>(x: &'a str, y: &'a str) -> &'a str { if x.len() > y.len() { x } else { y } } fn main() { let result; let string1 = String::from("Rust ownership"); { let string2 = String::from("borrowing"); result = longest(string1.as_str(), string2.as_str()); println!("Longest: {}", result); // valid: both strings alive } // println!("{}", result); // would fail: string2 dropped } ``` A anotacao `'a` indica que o retorno da funcao `longest` vivera pelo menos tanto quanto a menor lifetime entre `x` e `y`. Isso impede que a funcao retorne uma referencia para dados que ja foram liberados. Lifetimes sao um dos topicos mais desafiadores em entrevistas de Rust. O ponto-chave e compreender que lifetimes nao alteram o tempo de vida dos dados -- elas apenas descrevem as relacoes entre referencias para que o compilador possa verificar a seguranca. ## Lifetimes em Structs Quando uma struct armazena referencias em vez de dados proprios, ela precisa de anotacoes de lifetime. Isso garante que os dados referenciados vivam pelo menos tanto quanto a struct. ```rust // struct_lifetime.rs struct Excerpt<'a> { text: &'a str, } impl<'a> Excerpt<'a> { fn summary(&self) -> &str { let end = self.text.len().min(20); &self.text[..end] } } fn main() { let article = String::from("Rust ownership model eliminates memory bugs"); let excerpt = Excerpt { text: article.as_str(), }; println!("Summary: {}", excerpt.summary()); } ``` A struct `Excerpt` contem uma referencia `&str` com lifetime `'a`. Isso significa que qualquer instancia de `Excerpt` nao pode sobreviver alem dos dados que ela referencia. O compilador garante essa invariante em tempo de compilacao. Na pratica, muitas vezes e preferivel que structs possuam seus proprios dados (usando `String` em vez de `&str`), especialmente quando o tempo de vida dos dados nao e previsivel. Structs com lifetimes sao mais comuns em cenarios de alta performance onde evitar alocacoes e critico. ## Padroes de Ownership no Mundo Real Em aplicacoes reais, tres padroes de funcao aparecem com frequencia, dependendo de como a ownership e gerenciada: 1. **Receber ownership e retornar** -- util quando a funcao precisa modificar e devolver o valor. 2. **Borrowing imutavel** -- para funcoes que apenas leem dados sem modifica-los. 3. **Borrowing mutavel** -- para funcoes que modificam dados in-place sem assumir ownership. ```rust // ownership_patterns.rs fn process_and_return(mut input: String) -> String { input.push_str(" -- processed"); input } fn contains_keyword(text: &str, keyword: &str) -> bool { text.to_lowercase().contains(&keyword.to_lowercase()) } fn sanitize(input: &mut String) { *input = input.trim().to_string(); } fn main() { let raw = String::from("user input"); let processed = process_and_return(raw); let found = contains_keyword(&processed, "input"); println!("Contains 'input': {}", found); let mut padded = String::from(" spaces everywhere "); sanitize(&mut padded); println!("Sanitized: '{}'", padded); } ``` Escolher o padrao correto depende do contexto. Como regra geral: emprestar quando possivel, transferir ownership quando necessario. Em entrevistas, justificar essa escolha demonstra maturidade tecnica com a linguagem. ## Erros do Borrow Checker e Como Resolve-los O borrow checker e o componente do compilador Rust responsavel por validar todas as regras de ownership e borrowing. Inicialmente, seus erros podem parecer frustrantes, mas cada mensagem de erro previne um bug real de memoria. Abaixo estao tres situacoes comuns e suas solucoes: **Problema 1: Invalidacao de iterador.** Adicionar elementos a um vetor enquanto existe uma referencia ativa a um elemento pode causar realocacao, invalidando a referencia. A solucao e copiar o valor antes de modificar o vetor. **Problema 2: Move acidental.** Usar uma variavel `String` em uma formatacao pode transferir ownership. A funcao `format!` automaticamente empresta, resolvendo o problema. **Problema 3: Referencia a dado temporario.** Tentar referenciar um valor que sera descartado ao sair do escopo. A solucao e mover o valor para o escopo externo em vez de referencia-lo. ```rust // common_fixes.rs fn main() { let mut scores = vec![90, 85, 78]; let first = scores[0]; scores.push(95); println!("First: {}, All: {:?}", first, scores); let name = String::from("Alice"); let greeting = format!("Hello, {}", name); println!("{} says {}", name, greeting); let outer; { let inner = String::from("temporary"); outer = inner; } println!("{}", outer); } ``` No primeiro caso, `scores[0]` retorna um `i32` (tipo `Copy`), entao `first` recebe uma copia. Isso permite modificar `scores` logo em seguida. No segundo caso, `format!` empresta `name` automaticamente, preservando a ownership. No terceiro caso, `inner` tem sua ownership movida para `outer`, permitindo que o valor sobreviva alem do bloco interno. Compreender esses padroes de correcao e fundamental para resolver rapidamente erros do borrow checker, tanto em projetos reais quanto em avaliacoes tecnicas. ## Conclusao O modelo de ownership de Rust elimina categorias inteiras de bugs de memoria sem recorrer a garbage collection. Para entrevistas tecnicas, os pontos essenciais sao: - **Cada valor tem um unico proprietario.** Quando o proprietario sai do escopo, o valor e liberado automaticamente. - **Move semantics transferem ownership.** Apos um move, a variavel original nao pode mais ser utilizada. - **Borrowing permite acesso sem transferencia.** Referencias imutaveis (`&T`) para leitura e mutaveis (`&mut T`) para escrita. - **A regra de exclusividade previne data races.** Apenas uma referencia mutavel ou multiplas imutaveis, nunca ambas simultaneamente. - **Lifetimes descrevem relacoes entre referencias.** Permitem ao compilador verificar que referencias nao sobrevivem alem dos dados que apontam. - **O borrow checker e um aliado.** Cada erro de compilacao previne um bug real de seguranca de memoria. Dominar esses conceitos nao apenas prepara para entrevistas -- transforma a forma como se pensa sobre gerenciamento de recursos em qualquer linguagem de programacao. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/pt/blog/rust/rust-ownership-borrowing-demystified