---
title: "Optional em Zig — O que é e Como Usar"
url: "https://ziglang.com.br/glossario/optional-em-zig-o-que-%C3%A9-e-como-usar/"
markdown_url: "https://ziglang.com.br/glossario/optional-em-zig-o-que-%C3%A9-e-como-usar.MD"
description: "Entenda Optional (?) em Zig: o tipo que representa um valor que pode ser null de forma segura. Elimine null pointer bugs. Guia em pt-BR."
date: "2026-02-21"
author: "Zig Brasil"
---

# Optional em Zig — O que é e Como Usar

Entenda Optional (?) em Zig: o tipo que representa um valor que pode ser null de forma segura. Elimine null pointer bugs. Guia em pt-BR.


# Optional em Zig — O que é e Como Usar

## Definição

Um **Optional** em Zig é um tipo representado pelo operador `?` que pode conter **ou** um valor válido do tipo `T` **ou** `null`. A sintaxe `?T` declara um optional do tipo `T`. Diferentemente de linguagens como C onde qualquer ponteiro pode ser null, em Zig a possibilidade de nulidade é **explícita no sistema de tipos**.

Optionals eliminam uma das maiores fontes de bugs em programação: o acesso a valores nulos sem verificação.

## Por que Optionals Importam

1. **Null safety**: O compilador obriga você a verificar se o valor existe antes de usá-lo.
2. **Expressividade**: A assinatura da função comunica claramente que "pode não haver valor".
3. **Zero custo**: Para ponteiros, `?*T` tem o mesmo tamanho que `*T` (null é representado como 0).
4. **Diferente de erro**: Optional indica ausência, não falha. Use [Error Union](/glossario/error-union/) quando houver motivo da falha.

## Exemplo Prático

### Uso Básico

```zig
const std = @import("std");

fn encontrar(haystack: []const u8, needle: u8) ?usize {
    for (haystack, 0..) |char, indice| {
        if (char == needle) return indice;
    }
    return null; // Não encontrou
}

pub fn main() void {
    const texto = "Zig Brasil";

    if (encontrar(texto, 'B')) |indice| {
        std.debug.print("Encontrado na posição {}\n", .{indice});
    } else {
        std.debug.print("Não encontrado\n", .{});
    }
}
```

### Unwrap com `orelse`

```zig
const valor: ?u32 = null;
const resultado = valor orelse 42; // resultado = 42

const outro: ?u32 = 10;
const resultado2 = outro orelse 42; // resultado2 = 10
```

### Unwrap com `if`

```zig
fn processar(talvez_dados: ?[]const u8) void {
    if (talvez_dados) |dados| {
        // dados é []const u8 — desembrulhado, sem null
        std.debug.print("Dados: {s}\n", .{dados});
    } else {
        std.debug.print("Sem dados\n", .{});
    }
}
```

### Unwrap com `while`

```zig
fn proximoValor(iterador: *Iterador) ?u32 {
    // retorna null quando acabar
}

// while com optional — itera até null
while (proximoValor(&iter)) |valor| {
    std.debug.print("{}\n", .{valor});
}
```

### Optional de Ponteiro

```zig
const Node = struct {
    valor: i32,
    proximo: ?*Node, // Ponteiro que pode ser null
};

fn ultimo(node: *Node) *Node {
    var atual = node;
    while (atual.proximo) |prox| {
        atual = prox;
    }
    return atual;
}
```

### Encadeamento com `.?`

```zig
const config: ?*Config = obterConfig();
// .? é equivalente a unwrap forçado (panic se null)
const porta = config.?.porta;
```

**Cuidado**: `.?` causa panic se o valor for null. Prefira `if` ou `orelse`.

## Optional vs Error Union

| Característica | `?T` (Optional) | `!T` (Error Union) |
|---------------|------------------|---------------------|
| Significa | Valor pode estar ausente | Operação pode falhar |
| Informação extra | Nenhuma (só null) | Qual erro ocorreu |
| Operador | `orelse` | `catch` |
| Exemplo | Busca em lista | Leitura de arquivo |

## Armadilhas Comuns

- **Usar `.?` sem verificação**: O unwrap forçado (`.?`) causa panic se o valor for null. Use `if` ou `orelse` para segurança.
- **Confundir `?T` com `!T`**: Optional indica ausência; error union indica falha com motivo. Escolha o tipo correto.
- **Optionals aninhados**: `??T` é válido mas raramente útil e pode causar confusão. Repense o design se chegar nesse ponto.
- **Usar optional quando um valor default é melhor**: Se sempre há um valor razoável de fallback, considere usar o valor diretamente em vez de optional.

## Boas Práticas com Optionals

**Prefira `if` ou `orelse` ao `.?`**: O unwrap forçado (`.?`) é conveniente mas perigoso. Reserve-o para casos onde o valor null é genuinamente impossível (similar ao `unreachable`).

**Escolha entre `?T` e `!T` com cuidado**: Se a ausência de um valor é uma situação normal esperada (busca em mapa, índice não encontrado), use `?T`. Se a ausência indica uma falha que o chamador precisa tratar (arquivo não existe, permissão negada), use `!T`.

```zig
// BOM: busca pode não encontrar nada — ausência é esperada
fn buscarNoCachê(chave: []const u8) ?[]const u8 { ... }

// BOM: leitura de arquivo pode falhar — falha precisa de diagnóstico
fn lerArquivo(path: []const u8) ![]u8 { ... }
```

**Optional em structs para campos opcionais**:

```zig
const Usuario = struct {
    nome: []const u8,
    email: []const u8,
    avatar_url: ?[]const u8 = null, // Nem todo usuário tem avatar
    ultimo_acesso: ?i64 = null,     // Pode nunca ter acessado
};

fn exibirPerfil(usuario: Usuario) void {
    std.debug.print("Nome: {s}\n", .{usuario.nome});
    if (usuario.avatar_url) |url| {
        std.debug.print("Avatar: {s}\n", .{url});
    }
}
```

## Comparação com Outras Linguagens

Em C e C++, qualquer ponteiro pode ser null sem aviso — o programador precisa lembrar de checar. Em Java, todos os tipos de referência podem ser null, gerando `NullPointerException` em runtime. Em Kotlin e Swift, existe o conceito de "nullable" explícito com `?` (similar ao Zig). Em Rust, o tipo `Option<T>` é equivalente direto. A diferença do Zig é que optionals de ponteiro (`?*T`) não têm overhead: null é literalmente o endereço zero, sem campo adicional.

## Termos Relacionados

- [Orelse](/glossario/orelse/) — Operador para desembrulhar optionals
- [Error Union](/glossario/error-union/) — Tipo para erros com informação
- [Pointer Types](/glossario/pointer-types/) — Tipos de ponteiro em Zig
- [Undefined](/glossario/undefined/) — Valor indefinido

## Tutoriais Relacionados

- [Introdução ao Zig](/tutoriais/introducao-ao-zig/)
- [Strings e Arrays em Zig](/tutoriais/strings-e-arrays-zig/)
- [Zig para Programadores C](/tutoriais/zig-para-programadores-c/)
