image

Bootcamps ilimitados + curso de inglês para sempre

82
%OFF
Article image

CT

Carlos Tavares01/06/2026 08:57
Compartilhe

O Tipo Unit () em Rust: Compreendendo Retornos e Expressões.

  • #Rust

Fala galera, bora falar sobre o tipo Unit?

No Rust, quase tudo é uma expressão que precisa retornar algum valor. Mas o que acontece quando uma função ou bloco simplesmente não tem nada útil para devolver? É aí que entra o Unit Type, representado por "()".

Diferente do "void" do C++ ou Java (que indica a ausência total de um tipo), o "()" no Rust é um tipo real, que possui um único valor possível: "()". O compilador o trata como um “Zero-Sized Type“ (ZST). Na prática, isso significa que ele tem tamanho zero em memória (std::mem::size_of::<()>() == 0) e é totalmente otimizado no binário final, sem gastar um único byte em tempo de execução.

Abaixo estão os pontos principais de como ele funciona no dia a dia e onde o compilador costuma pegar quem está começando.

Retornos Implícitos vs explícitos:

Se você não define um tipo de retorno (usando "->") na assinatura de uma função, o compilador assume automaticamente que ela retorna "()".

Rust

//rust
// O padrão que usamos no dia a dia:
fn rotina_de_limpeza() {
 let temp_files = 10;
 println!("Limpando {} arquivos temporários...", temp_files);
}
O que o compilador enxerga por baixo dos panos:
//rust
fn rotina_de_limpeza_explicita() -> () {
 let temp_files = 10;
 println!("Limpando {} arquivos temporários...", temp_files);
 return (); 
}

A Armadilha do Ponto e Vírgula

Esse é um dos erros mais comuns para quem está entrando no ecossistema do Rust. Colocar ou omitir um ponto e vírgula (;) muda completamente o tipo de retorno de um bloco de código, porque o ; transforma uma expressão em um statement (instrução), descartando o valor e gerando ().

Rust

// rust 
fn avaliar_blocos() {
 // Sem ponto e vírgula: o bloco retorna o i32 (10)
 let valor_real: i32 = {
     let x = 5;
     x + 5 
 };
   Com ponto e vírgula: o valor 10 é descartado e o bloco retorna ()
 let valor_descartado: () = {
     let x = 5;
     x + 5; 
 };
 assert_eq!(valor_descartado, ());
}

Generics e Tratamento de Erros

O grande trunfo do () ser um tipo real (e não uma palavra-chave como void) aparece quando lidamos com tipos genéricos, especialmente no Result<T, E>. Quando uma função pode dar erro, mas o sucesso dela significa apenas que a tarefa foi cumprida (sem precisar devolver nenhum dado de volta), usamos () no lugar do T.

//rust
use std::fs::File;
use std::io::Error;

// "Retorna nada em caso de sucesso, ou um Error se falhar"
fn inicializar_sistema(config_path: &str) -> Result<(), Error> {
 let _file = File::open(config_path)?;
 
 // Sucesso absoluto: encapsula o unit value no Ok
 Ok(())
}

fn main() {
 match inicializar_sistema("/etc/config.toml") {
     Ok(()) => println!("Sistema pronto."),
     Err(e) => eprintln!("Erro na inicialização: {}", e),
 }
}

() vs ! (Never Type)

Uma dúvida comum é a diferença entre () e o tipo !. A lógica é simples:

  • () (Unit): A função executa até o fim e termina normalmente, mas não produz nenhum dado relevante.
  • ! (Never): A função nunca retorna para quem a chamou. Ela quebra o fluxo de execução, seja por causa de um panic!(), um loop {} infinito ou um encerramento do processo (std::process::exit()).
Resumindo: () significa "terminei, mas não tenho nada para te entregar"; ! significa "daqui eu não volto".
Compartilhe
Recomendados para você
GFT - Fundamentos de Cloud com AWS
Bootcamp Bradesco - GenAI, Dados & Cyber
Bootcamp Afya - Automação de Dados com IA
Comentários (0)