---
title: "Error Union em Zig — O que é e Como Usar"
url: "https://ziglang.com.br/glossario/error-union-em-zig-o-que-%C3%A9-e-como-usar/"
markdown_url: "https://ziglang.com.br/glossario/error-union-em-zig-o-que-%C3%A9-e-como-usar.MD"
description: "Entenda Error Union (!) em Zig: o tipo que pode conter um valor ou um erro. Base do tratamento de erros da linguagem. Guia em pt-BR."
date: "2026-02-21"
author: "Zig Brasil"
---

# Error Union em Zig — O que é e Como Usar

Entenda Error Union (!) em Zig: o tipo que pode conter um valor ou um erro. Base do tratamento de erros da linguagem. Guia em pt-BR.


# Error Union em Zig — O que é e Como Usar

## Definição

Um **Error Union** em Zig é um tipo composto representado pelo operador `!` que pode conter **ou** um valor válido **ou** um erro. É o mecanismo fundamental de tratamento de erros da linguagem, substituindo exceções (como em Java/Python) e códigos de retorno (como em C).

A sintaxe `ErrorSet!T` significa "este valor é do tipo `T` ou é um erro do conjunto `ErrorSet`". Quando o error set é omitido (`!T`), o compilador infere o conjunto de erros automaticamente.

## Por que Error Unions Importam

1. **Erros são valores**: Em Zig, erros são cidadãos de primeira classe no sistema de tipos — não são exceções invisíveis.
2. **Impossível ignorar erros**: O compilador obriga você a lidar com o caso de erro explicitamente.
3. **Zero custo**: Error unions são implementados de forma eficiente, sem overhead de exceções.
4. **Composição**: Funções que retornam error unions se compõem naturalmente com `try`.

## Exemplo Prático

### Retornando Error Unions

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

const MathError = error{
    DivisaoPorZero,
    Overflow,
};

fn dividir(a: i32, b: i32) MathError!i32 {
    if (b == 0) return MathError.DivisaoPorZero;
    return @divTrunc(a, b);
}

pub fn main() void {
    // Tratando o erro explicitamente
    const resultado = dividir(10, 3) catch |err| {
        std.debug.print("Erro: {}\n", .{err});
        return;
    };
    std.debug.print("10 / 3 = {}\n", .{resultado});
}
```

### Usando com `try`

```zig
fn processarDados() !void {
    const valor = try dividir(100, 5);  // Propaga erro automaticamente
    std.debug.print("Resultado: {}\n", .{valor});
}
```

`try` é equivalente a:

```zig
const valor = dividir(100, 5) catch |err| return err;
```

### Usando com `if`

```zig
fn exemploIf() void {
    if (dividir(10, 0)) |valor| {
        std.debug.print("Sucesso: {}\n", .{valor});
    } else |err| {
        std.debug.print("Erro: {}\n", .{err});
    }
}
```

### Error Union com tipo inferido

```zig
// O compilador infere o error set automaticamente
fn lerArquivo(caminho: []const u8) ![]const u8 {
    const arquivo = try std.fs.cwd().openFile(caminho, .{});
    defer arquivo.close();
    return try arquivo.readToEndAlloc(std.heap.page_allocator, 1024 * 1024);
}
```

## Anatomia do Tipo

```
ErrorSet ! PayloadType
   │          │
   │          └── Tipo do valor em caso de sucesso
   └── Conjunto de possíveis erros

Exemplos:
  error{OutOfMemory}![]u8     — Pode ser OutOfMemory ou um slice de bytes
  anyerror!void               — Qualquer erro ou void (sem valor)
  !u32                        — Error set inferido, valor u32
```

## Combinando Error Sets

Quando uma função chama outras que retornam diferentes error sets, o compilador infere a união automaticamente:

```zig
const IoError = error{ DiskFull, PermissionDenied };
const ParseError = error{ InvalidFormat, UnexpectedEof };

// O compilador infere o tipo como IoError || ParseError
fn lerEProcessar(caminho: []const u8) !u32 {
    const conteudo = try lerArquivo(caminho);   // retorna IoError![]u8
    const numero = try parsear(conteudo);        // retorna ParseError!u32
    return numero;
}
```

Você também pode combinar error sets explicitamente com `||`:

```zig
const ErrosCombinados = IoError || ParseError;

fn funcao() ErrosCombinados!void {
    // ...
}
```

## Error Union vs Outros Mecanismos de Erro

| Mecanismo | Linguagem | Pode ignorar? | Overhead | Informação |
|-----------|-----------|--------------|----------|-----------|
| Error Union `!T` | Zig | Não (compilador força) | Zero | Error set tipado |
| `Result<T,E>` | Rust | Não (com warnings) | Zero | Tipo genérico |
| Exceções | Java, Python | Sim (silencioso) | Alto (stack unwinding) | Classe de exceção |
| Código de retorno `int` | C | Sim (fácil de esquecer) | Zero | Apenas um inteiro |
| `errno` global | C | Sim | Zero | Código global mágico |

A principal vantagem do error union sobre exceções é o custo zero: não há stack unwinding, não há heap allocation para o objeto de exceção, e o compilador garante que todos os erros sejam tratados.

## Boas Práticas

- **Prefira error sets específicos a `anyerror`**: Error sets nomeados documentam o contrato da função e permitem que o compilador verifique exaustividade em switches de erro.
- **Use `errdefer` para cleanup em caso de falha**: Quando a função aloca recursos antes de um possível erro, `errdefer` garante que o cleanup ocorra apenas em caso de falha (ao contrário de `defer`, que sempre executa).
- **Documente erros possíveis**: Mesmo que o compilador infira o error set, listar os erros possíveis em comentários ajuda quem usa a API.
- **Propague com `try`, não com `catch unreachable`**: Se não souber tratar o erro, propague-o. `catch unreachable` é uma bomba-relógio se a premissa estiver errada.

## Armadilhas Comuns

- **Usar `anyerror` desnecessariamente**: Prefira error sets específicos. `anyerror` desabilita otimizações do compilador e dificulta a documentação da API.
- **Ignorar erros com `catch unreachable`**: Só use quando tiver **certeza absoluta** de que o erro não pode ocorrer. Caso contrário, isso causará um panic em runtime.
- **Confundir `!T` com `?T`**: Error union (`!T`) carrega informação de erro; optional (`?T`) apenas indica presença/ausência de valor.
- **Não propagar erros**: Se sua função não sabe lidar com o erro, propague-o com `try` em vez de engolir silenciosamente.

## Termos Relacionados

- [Error Set](/glossario/error-set/) — Conjuntos de erros nomeados
- [Try](/glossario/try/) — Operador de propagação de erros
- [Catch](/glossario/catch/) — Operador para capturar erros
- [Optional](/glossario/optional/) — Tipo que pode ser null
- [Errdefer](/glossario/errdefer/) — Defer condicional para erros

## Tutoriais Relacionados

- [Tratamento de Erros em Zig](/tutoriais/tratamento-de-erros-em-zig/)
- [Introdução ao Zig](/tutoriais/introducao-ao-zig/)
- [Zig para Programadores C](/tutoriais/zig-para-programadores-c/)
