---
title: "Perguntas de Entrevista sobre Error Handling em Zig"
url: "https://ziglang.com.br/entrevistas/perguntas-de-entrevista-sobre-error-handling-em-zig/"
markdown_url: "https://ziglang.com.br/entrevistas/perguntas-de-entrevista-sobre-error-handling-em-zig.MD"
description: "Perguntas de entrevista sobre tratamento de erros em Zig: error unions, try/catch, error sets, errdefer, propagação de erros e boas práticas."
date: "2026-02-21"
author: "Zig Brasil"
---

# Perguntas de Entrevista sobre Error Handling em Zig

Perguntas de entrevista sobre tratamento de erros em Zig: error unions, try/catch, error sets, errdefer, propagação de erros e boas práticas.


# Perguntas de Entrevista sobre Error Handling em Zig

O sistema de tratamento de erros de Zig é um dos seus diferenciais mais importantes. Diferente de exceções (Java, Python, C++), códigos de retorno (C), ou `Result` types (Rust), Zig usa error unions que combinam o melhor dessas abordagens. Entrevistadores testam este tema extensivamente porque demonstra compreensão profunda da filosofia da linguagem.

## Conceitos Fundamentais

### Explique o que são error unions em Zig.

Um error union (`!T`) é um tipo que pode conter um valor de sucesso de tipo `T` ou um valor de erro de um error set. É o mecanismo principal de tratamento de erros em Zig:

```zig
fn dividir(a: f64, b: f64) !f64 {
    if (b == 0) return error.DivisaoPorZero;
    return a / b;
}
```

O tipo retornado é `error{DivisaoPorZero}!f64` — ou sucesso com `f64`, ou o erro `DivisaoPorZero`.

### Qual a diferença entre `try`, `catch` e `if` para error handling?

**`try`:** Propaga o erro para o chamador. Equivalente a `expr catch |err| return err`:
```zig
const resultado = try dividir(10, 0); // propaga o erro
```

**`catch`:** Captura e trata o erro localmente:
```zig
const resultado = dividir(10, 0) catch |err| {
    std.log.err("Erro: {}", .{err});
    return err;
};

// Ou com valor default
const resultado = dividir(10, 0) catch 0;
```

**`if` com error union:**
```zig
if (dividir(10, 0)) |valor| {
    // usar valor
} else |err| {
    // tratar erro
}
```

### O que são error sets e como eles se compõem?

Error sets são conjuntos de erros possíveis que uma função pode retornar:

```zig
const FileError = error{
    NotFound,
    PermissionDenied,
    OutOfMemory,
};

const NetworkError = error{
    ConnectionRefused,
    Timeout,
    OutOfMemory,
};

// Union de error sets
const AppError = FileError || NetworkError;
```

Zig usa interseção e união de error sets para determinar automaticamente quais erros uma função pode retornar. O compilador rastreia error sets em tempo de compilação.

### Explique `errdefer` e quando usá-lo.

`errdefer` executa uma expressão apenas quando a função retorna um erro. É essencial para cleanup parcial:

```zig
fn inicializar(allocator: Allocator) !*Sistema {
    const memoria = try allocator.alloc(u8, 1024);
    errdefer allocator.free(memoria); // libera se falhar abaixo

    const config = try carregarConfig();
    errdefer config.deinit(); // limpa se falhar abaixo

    const conexao = try conectarBD();
    // Se tudo OK, caller é responsável pelo cleanup

    return Sistema{ .memoria = memoria, .config = config, .conexao = conexao };
}
```

Sem `errdefer`, seria necessário try-catch manual para cada operação, tornando o código verboso e propenso a leaks.

## Perguntas Intermediárias

### Quando usar `catch unreachable` vs `catch` com tratamento?

`catch unreachable` indica que você tem certeza absoluta que o erro não pode ocorrer. O compilador gera um panic se o erro ocorrer em modo debug:

```zig
// OK: sabemos que o slice tem pelo menos 1 elemento
const primeiro = items[0]; // se items é empty, panic

// Em funções onde o error set é logicamente impossível
var list = std.ArrayList(u8).init(allocator);
list.appendAssumeCapacity(42); // precisa ter capacidade garantida
```

Use `catch unreachable` raramente e apenas quando puder provar logicamente que o erro é impossível. Na dúvida, trate o erro.

### Como Zig trata erros de alocação de memória?

Alocação em Zig pode falhar (retornar `error.OutOfMemory`), e funções que alocam retornam error unions. Isso força tratamento explícito:

```zig
fn processarDados(allocator: Allocator, dados: []const u8) ![]u8 {
    const resultado = try allocator.alloc(u8, dados.len * 2);
    errdefer allocator.free(resultado);
    // ... processar ...
    return resultado;
}
```

Diferente de C onde `malloc` retorna NULL (facilmente ignorado) ou C++ onde `new` lança exceção (facilmente não capturada), Zig torna impossível ignorar falha de alocação.

### Como converter entre error sets?

```zig
const SpecificError = error{NotFound, PermissionDenied};
const BroadError = error{NotFound, PermissionDenied, Timeout, OutOfMemory};

fn funcaoEspecifica() SpecificError!void {
    return error.NotFound;
}

fn funcaoAmpla() BroadError!void {
    // Funciona: SpecificError é subconjunto de BroadError
    try funcaoEspecifica();
    return error.Timeout;
}
```

Error sets de subconjuntos são automaticamente coercidos para superconjuntos. O inverso requer tratamento explícito.

## Cenários Práticos

### Implemente retry com backoff usando error handling de Zig.

```zig
fn comRetry(comptime maxTentativas: u32, operacao: anytype) !@TypeOf(operacao()).Payload {
    var tentativa: u32 = 0;
    while (tentativa < maxTentativas) : (tentativa += 1) {
        if (operacao()) |resultado| {
            return resultado;
        } else |err| {
            if (tentativa + 1 >= maxTentativas) return err;
            std.time.sleep(std.time.ns_per_ms * (@as(u64, 100) << @intCast(tentativa)));
        }
    }
    unreachable;
}
```

### Como Zig se compara com outras linguagens no tratamento de erros?

| Aspecto | Zig | C | Rust | Go | Java |
|---------|-----|---|------|-----|------|
| Mecanismo | Error unions | Códigos retorno | Result<T,E> | Múltiplos retornos | Exceções |
| Propagação | `try` | Manual | `?` operator | `if err != nil` | throws |
| Ignorar erro | Impossível | Fácil | Possível com `unwrap` | Fácil com `_` | Possível |
| Performance | Zero overhead | Zero overhead | Zero overhead | Low overhead | Stack unwinding |
| Cleanup | `errdefer` | Goto cleanup | Drop trait | `defer` | `finally` |

## Boas Práticas

1. **Nunca ignore erros** — trate ou propague explicitamente
2. **Use `errdefer` para cleanup** — garanta liberação de recursos em caso de erro
3. **Error sets específicos** — defina error sets que comunicam claramente o que pode falhar
4. **Evite `catch unreachable`** — a menos que possa provar logicamente que o erro é impossível
5. **Documente erros** — use doc comments para explicar quando cada erro ocorre

## Preparação Complementar

- [Perguntas de memória](/entrevistas/perguntas-memoria-zig/) — error handling e memória são intimamente ligados
- [Perguntas básicas](/entrevistas/perguntas-basicas-zig/) — fundamentos da linguagem
- [Design patterns](/entrevistas/perguntas-design-patterns-zig/) — padrões que envolvem error handling
- [Desafios de código](/entrevistas/desafio-codigo-zig-1/) — pratique implementação
- [Tutoriais](/tutoriais/) para exemplos práticos
