---
title: "Option\u003cT\u003e em Rust: Some e None"
url: "https://rustlang.com.br/stdlib/option/"
markdown_url: "https://rustlang.com.br/stdlib/option.MD"
description: "Guia completo de Option\u003cT\u003e em Rust: pattern matching, unwrap, map, and_then, operador ?, conversão para Result e exemplos práticos."
date: "2026-02-23"
author: "Equipe Rust Brasil"
---

# Option<T> em Rust: Some e None

Guia completo de Option<T> em Rust: pattern matching, unwrap, map, and_then, operador ?, conversão para Result e exemplos práticos.


## O que é Option\<T\>

`Option<T>` é o tipo que Rust usa para representar valores que podem ou não existir. Ele tem exatamente duas variantes: `Some(T)` quando há um valor presente, e `None` quando não há. Diferente de linguagens que usam `null` ou `nil`, o `Option` força você a lidar explicitamente com a ausência de valor, eliminando a categoria inteira de erros de null pointer em tempo de compilação.

Use `Option<T>` sempre que uma função pode não retornar um resultado (busca em uma coleção, parsing opcional, primeiro elemento de uma lista vazia), ou quando um campo de uma struct é opcional. Praticamente todo código Rust usa `Option` intensivamente — ele está no prelude e pode ser usado sem importar nada.

---

## Criando e Usando Option

```rust
fn main() {
    // Criando diretamente
    let algum_valor: Option<i32> = Some(42);
    let nenhum_valor: Option<i32> = None;

    // Retornado por métodos da stdlib
    let numeros = vec![10, 20, 30];
    let primeiro: Option<&i32> = numeros.first();     // Some(&10)
    let decimo: Option<&i32> = numeros.get(9);         // None

    let texto = "42abc";
    let resultado: Option<usize> = texto.find('a');    // Some(2)

    // Pattern matching — a forma mais completa
    match primeiro {
        Some(valor) => println!("Primeiro: {valor}"),
        None => println!("Lista vazia"),
    }

    // if let — quando só interessa o caso Some
    if let Some(pos) = resultado {
        println!("Encontrado na posição {pos}");
    }

    // let-else — quando None é o caso de erro (Rust 1.65+)
    let Some(val) = algum_valor else {
        println!("Sem valor!");
        return;
    };
    println!("Valor: {val}");

    println!("{nenhum_valor:?} {decimo:?}");
}
```

---

## Tabela de Métodos Principais

| Método | Descrição | Exemplo |
|---|---|---|
| `is_some()` | Retorna `true` se é `Some` | `Some(1).is_some()` → `true` |
| `is_none()` | Retorna `true` se é `None` | `None::<i32>.is_none()` → `true` |
| `unwrap()` | Extrai o valor ou **panic** | `Some(1).unwrap()` → `1` |
| `unwrap_or(default)` | Extrai ou retorna default | `None.unwrap_or(0)` → `0` |
| `unwrap_or_else(f)` | Extrai ou calcula via closure | `None.unwrap_or_else(\|\| calcular())` |
| `unwrap_or_default()` | Extrai ou usa `Default::default()` | `None::<i32>.unwrap_or_default()` → `0` |
| `expect(msg)` | Como `unwrap` mas com mensagem de panic | `opt.expect("erro")` |
| `map(f)` | Transforma o valor interno | `Some(1).map(\|x\| x * 2)` → `Some(2)` |
| `map_or(default, f)` | Transforma ou retorna default | `None.map_or(0, \|x\| x * 2)` → `0` |
| `and_then(f)` | Encadeia operações que retornam `Option` | `Some(1).and_then(\|x\| Some(x + 1))` |
| `filter(pred)` | `None` se o predicado falhar | `Some(4).filter(\|x\| x % 2 == 0)` → `Some(4)` |
| `or(outra)` | Retorna `self` se `Some`, senão `outra` | `None.or(Some(5))` → `Some(5)` |
| `or_else(f)` | Como `or`, mas com closure | `None.or_else(\|\| Some(5))` |
| `zip(outra)` | Combina dois Options em tupla | `Some(1).zip(Some("a"))` → `Some((1, "a"))` |
| `flatten()` | Achata `Option<Option<T>>` | `Some(Some(1)).flatten()` → `Some(1)` |
| `ok_or(err)` | Converte para `Result<T, E>` | `Some(1).ok_or("erro")` → `Ok(1)` |
| `ok_or_else(f)` | Converte para `Result` com closure | `None.ok_or_else(\|\| "erro")` |
| `as_ref()` | `Option<&T>` a partir de `&Option<T>` | `opt.as_ref()` |
| `take()` | Pega o valor, deixando `None` | `opt.take()` |
| `replace(val)` | Substitui o valor, retornando o antigo | `opt.replace(5)` |

---

## Exemplos Práticos

### 1. Encadeando Transformações com map e and_then

```rust
fn buscar_usuario(id: u64) -> Option<String> {
    match id {
        1 => Some("Ana Silva".to_string()),
        2 => Some("Bruno Costa".to_string()),
        _ => None,
    }
}

fn extrair_primeiro_nome(nome_completo: &str) -> Option<&str> {
    nome_completo.split_whitespace().next()
}

fn main() {
    // Encadeando operações que podem falhar
    let saudacao = buscar_usuario(1)
        .as_deref()  // Option<String> → Option<&str>
        .and_then(extrair_primeiro_nome)
        .map(|nome| format!("Olá, {nome}!"))
        .unwrap_or_else(|| "Usuário não encontrado".to_string());

    println!("{saudacao}"); // "Olá, Ana!"

    // Com usuário inexistente
    let saudacao2 = buscar_usuario(99)
        .as_deref()
        .and_then(extrair_primeiro_nome)
        .map(|nome| format!("Olá, {nome}!"))
        .unwrap_or_else(|| "Usuário não encontrado".to_string());

    println!("{saudacao2}"); // "Usuário não encontrado"
}
```

### 2. O Operador ? com Option

```rust
#[derive(Debug)]
struct Endereco {
    rua: String,
    numero: Option<u32>,
    complemento: Option<String>,
}

#[derive(Debug)]
struct Pessoa {
    nome: String,
    endereco: Option<Endereco>,
}

fn obter_complemento(pessoa: &Pessoa) -> Option<&str> {
    // O operador ? retorna None imediatamente se qualquer etapa for None
    pessoa
        .endereco
        .as_ref()?
        .complemento
        .as_deref()
}

fn main() {
    let pessoa1 = Pessoa {
        nome: "Ana".into(),
        endereco: Some(Endereco {
            rua: "Rua das Flores".into(),
            numero: Some(42),
            complemento: Some("Apto 301".into()),
        }),
    };

    let pessoa2 = Pessoa {
        nome: "Bruno".into(),
        endereco: None,
    };

    println!("{}: {:?}", pessoa1.nome, obter_complemento(&pessoa1)); // Some("Apto 301")
    println!("{}: {:?}", pessoa2.nome, obter_complemento(&pessoa2)); // None
}
```

### 3. Convertendo entre Option e Result

```rust
use std::num::ParseIntError;

fn buscar_config(chave: &str) -> Option<String> {
    match chave {
        "porta" => Some("8080".to_string()),
        "host" => Some("localhost".to_string()),
        _ => None,
    }
}

fn obter_porta() -> Result<u16, String> {
    buscar_config("porta")
        .ok_or_else(|| "Chave 'porta' não encontrada".to_string())?
        .parse::<u16>()
        .map_err(|e: ParseIntError| format!("Porta inválida: {e}"))
}

fn main() {
    match obter_porta() {
        Ok(porta) => println!("Servidor rodando na porta {porta}"),
        Err(erro) => eprintln!("Erro: {erro}"),
    }
}
```

### 4. Combinando Múltiplos Options com zip

```rust
fn calcular_imc(peso_kg: Option<f64>, altura_m: Option<f64>) -> Option<f64> {
    peso_kg
        .zip(altura_m)
        .filter(|(_, a)| *a > 0.0)
        .map(|(p, a)| p / (a * a))
}

fn classificar_imc(imc: f64) -> &'static str {
    match imc {
        x if x < 18.5 => "Abaixo do peso",
        x if x < 25.0 => "Peso normal",
        x if x < 30.0 => "Sobrepeso",
        _ => "Obesidade",
    }
}

fn main() {
    let resultado = calcular_imc(Some(70.0), Some(1.75))
        .map(|imc| format!("IMC: {imc:.1} - {}", classificar_imc(imc)))
        .unwrap_or_else(|| "Dados insuficientes".to_string());

    println!("{resultado}"); // "IMC: 22.9 - Peso normal"

    let incompleto = calcular_imc(Some(70.0), None);
    println!("{incompleto:?}"); // None
}
```

### 5. Coletando Options em um Vec

```rust
fn main() {
    let entradas = vec!["42", "abc", "7", "xyz", "100"];

    // collect() descarta os None automaticamente com flatten
    let numeros: Vec<i32> = entradas
        .iter()
        .map(|s| s.parse::<i32>().ok()) // Cada parse retorna Option<i32>
        .flatten()                        // Remove os None
        .collect();
    println!("Números: {numeros:?}"); // [42, 7, 100]

    // Alternativa com filter_map (equivalente a map + flatten)
    let numeros2: Vec<i32> = entradas
        .iter()
        .filter_map(|s| s.parse().ok())
        .collect();
    println!("Números: {numeros2:?}"); // [42, 7, 100]

    // collect() que falha no primeiro None
    let todos: Option<Vec<i32>> = vec!["1", "2", "3"]
        .iter()
        .map(|s| s.parse().ok())
        .collect();
    println!("Todos: {todos:?}"); // Some([1, 2, 3])

    let com_falha: Option<Vec<i32>> = vec!["1", "abc", "3"]
        .iter()
        .map(|s| s.parse().ok())
        .collect();
    println!("Com falha: {com_falha:?}"); // None
}
```

---

## Dicas de Performance e Armadilhas

1. **Evite `unwrap()` em produção**: Use `unwrap()` apenas em testes, protótipos ou quando tiver certeza absoluta de que o valor é `Some`. Prefira `unwrap_or`, `unwrap_or_else`, ou pattern matching.

2. **`map` vs `and_then`**: Use `map` quando a transformação sempre retorna um valor. Use `and_then` quando a transformação também pode falhar (retorna `Option`). Usar `map` com uma função que retorna `Option` gera `Option<Option<T>>`.

3. **Custo zero**: `Option<T>` não tem overhead de memória quando `T` é uma referência ou `NonZero*`. O compilador usa a representação nula para `None`, eliminando o byte extra.

4. **`as_ref()` para evitar movimentos**: Quando tiver `&Option<T>` e precisar de `Option<&T>`, use `as_ref()`. Isso evita mover o valor para fora do Option.

5. **`take()` para extrair valores**: `option.take()` substitui o valor por `None` e retorna o antigo. Útil quando precisa mover o valor de dentro de uma struct sem clonar.

6. **`Option` em iteradores**: Iteradores possuem métodos como `filter_map` e `find` que trabalham naturalmente com `Option`, evitando verificações manuais.

---

## Veja Também

- [Tratamento de Erros em Rust](/tutoriais/tratamento-de-erros/) — tutorial completo com Option e Result
- [Result\<T,E\>: Ok e Err](/stdlib/result/) — o tipo irmão para erros recuperáveis
- [Iterator Trait](/stdlib/iterator/) — trabalha intensivamente com Option
- [HashMap\<K,V\>](/stdlib/hashmap/) — `get()` retorna `Option<&V>`
- [Vec\<T\>](/stdlib/vec/) — `first()`, `last()`, `get()` retornam Option
- [Cheatsheet Rust](/cheatsheet/) — referência rápida de sintaxe
- [Documentação oficial — std::option::Option](https://doc.rust-lang.org/std/option/enum.Option.html)
