---
title: "Padrões Try/Catch de Erros em Zig"
url: "https://ziglang.com.br/receitas/padr%C3%B5es-try/catch-de-erros-em-zig/"
markdown_url: "https://ziglang.com.br/receitas/padr%C3%B5es-try/catch-de-erros-em-zig.MD"
description: "Receita prática de padrões de tratamento de erros em Zig com try e catch. Error unions, propagação, switch em erros, cleanup com errdefer e composição de erros."
date: "2026-02-21"
author: "Zig Brasil"
---

# Padrões Try/Catch de Erros em Zig

Receita prática de padrões de tratamento de erros em Zig com try e catch. Error unions, propagação, switch em erros, cleanup com errdefer e composição de erros.


## Introdução

Zig usa error unions em vez de exceções. Uma função que pode falhar retorna `!T` (error union), e o chamador deve tratar o erro com `try` (propagar) ou `catch` (tratar). Este é um dos aspectos mais elegantes de Zig.

Para error sets customizados, veja [Error Sets Customizados](/receitas/zig-error-set-customizado/). Para cleanup, consulte [Padrões Errdefer](/receitas/zig-errdefer-pattern/). Para o tutorial completo, veja [Tratamento de Erros em Zig](/tutoriais/tratamento-de-erros-em-zig/).

## Pré-requisitos

- Zig instalado (versão 0.13+). Veja o [guia de instalação](/tutoriais/como-instalar-zig/)
- Conhecimento básico de Zig. Consulte a [introdução ao Zig](/tutoriais/introducao-ao-zig/)

## Try: Propagar Erros

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

fn lerArquivo(caminho: []const u8) ![]u8 {
    // try propaga o erro para o chamador
    const arquivo = try std.fs.cwd().openFile(caminho, .{});
    defer arquivo.close();

    var buffer: [4096]u8 = undefined;
    const n = try arquivo.readAll(&buffer);
    return buffer[0..n];
}

fn processarConfig() !Config {
    const dados = try lerArquivo("config.txt");
    return try parsearConfig(dados);
}
```

`try` é equivalente a:
```zig
const resultado = funcao() catch |err| return err;
```

## Catch: Tratar Erros

### Catch com Handler

```zig
const valor = funcao() catch |err| {
    std.log.err("Falha: {}", .{err});
    return;
};
```

### Catch com Valor Padrão

```zig
const porta = std.fmt.parseInt(u16, porta_str, 10) catch 8080;
```

### Catch com Return

```zig
const arquivo = std.fs.cwd().openFile("dados.bin", .{}) catch |err| {
    std.debug.print("Erro ao abrir: {}\n", .{err});
    return err;
};
defer arquivo.close();
```

## Switch em Erros

```zig
const MeuErro = error{
    ArquivoNaoEncontrado,
    PermissaoNegada,
    FormatoInvalido,
    Timeout,
};

fn processar(caminho: []const u8) MeuErro!Resultado {
    // ...
}

fn executar() void {
    const resultado = processar("dados.txt") catch |err| switch (err) {
        error.ArquivoNaoEncontrado => {
            std.debug.print("Arquivo não encontrado\n", .{});
            return;
        },
        error.PermissaoNegada => {
            std.debug.print("Sem permissão\n", .{});
            return;
        },
        error.FormatoInvalido => {
            std.debug.print("Formato inválido\n", .{});
            return;
        },
        error.Timeout => {
            std.debug.print("Timeout\n", .{});
            return;
        },
    };
    _ = resultado;
}
```

## Compor Funções com Erros

```zig
fn pipeline(allocator: std.mem.Allocator, caminho: []const u8) !Resultado {
    const raw = try lerArquivo(allocator, caminho);
    defer allocator.free(raw);

    const parsed = try parsear(raw);
    const validado = try validar(parsed);
    const resultado = try transformar(allocator, validado);

    return resultado;
}
```

Cada `try` propaga o erro se a função falhar. O `defer` garante cleanup do `raw` independentemente de onde o erro ocorra.

## Erros em Loops

```zig
fn processarTodos(allocator: std.mem.Allocator, caminhos: []const []const u8) !void {
    for (caminhos) |caminho| {
        processar(allocator, caminho) catch |err| {
            std.log.warn("Falha em {s}: {}", .{ caminho, err });
            continue; // Continuar com o próximo
        };
    }
}

// Ou coletar resultados e erros
fn processarComResultados(
    allocator: std.mem.Allocator,
    caminhos: []const []const u8,
) !struct { sucessos: usize, falhas: usize } {
    var sucessos: usize = 0;
    var falhas: usize = 0;

    for (caminhos) |caminho| {
        if (processar(allocator, caminho)) |_| {
            sucessos += 1;
        } else |_| {
            falhas += 1;
        }
    }

    return .{ .sucessos = sucessos, .falhas = falhas };
}
```

## Retries

```zig
fn comRetry(comptime max_tentativas: usize, func: anytype, args: anytype) !@typeInfo(@TypeOf(@call(.auto, func, args))).error_union.payload {
    var tentativa: usize = 0;
    while (tentativa < max_tentativas) : (tentativa += 1) {
        if (@call(.auto, func, args)) |resultado| {
            return resultado;
        } else |err| {
            if (tentativa + 1 < max_tentativas) {
                std.time.sleep(std.time.ns_per_s * (tentativa + 1));
            } else {
                return err;
            }
        }
    }
    unreachable;
}
```

## Error Union com Optional

```zig
// Função que pode retornar erro, valor, ou "não encontrado"
fn buscar(id: u32) !?Resultado {
    if (id == 0) return error.IdInvalido;  // Erro
    if (id > 1000) return null;             // Não encontrado
    return Resultado{ .id = id };           // Sucesso
}

// Tratar os três casos
if (buscar(42)) |maybe_resultado| {
    if (maybe_resultado) |resultado| {
        std.debug.print("Encontrado: {}\n", .{resultado.id});
    } else {
        std.debug.print("Não encontrado\n", .{});
    }
} else |err| {
    std.debug.print("Erro: {}\n", .{err});
}
```

## Testes com Erros

```zig
test "função retorna erro esperado" {
    const resultado = dividir(10, 0);
    try std.testing.expectError(error.DivisaoPorZero, resultado);
}

test "função retorna valor correto" {
    const resultado = try dividir(10, 2);
    try std.testing.expectEqual(@as(f64, 5.0), resultado);
}
```

Veja [Testes Unitários](/receitas/zig-teste-unitario-basico/) e [Test Expectations](/receitas/zig-teste-expect-matchers/).

## Conclusão

O sistema de erros de Zig é simples e poderoso: `try` propaga, `catch` trata, e o compilador garante que todo erro é considerado. Sem exceções invisíveis, sem stack unwinding, sem overhead de runtime.

Para padrões relacionados, veja [Error Sets Customizados](/receitas/zig-error-set-customizado/), [Padrões Errdefer](/receitas/zig-errdefer-pattern/) e [Error Logging](/receitas/zig-error-logging/).
