---
title: "Defer em Zig — O que é e Como Usar"
url: "https://ziglang.com.br/glossario/defer-em-zig-o-que-%C3%A9-e-como-usar/"
markdown_url: "https://ziglang.com.br/glossario/defer-em-zig-o-que-%C3%A9-e-como-usar.MD"
description: "Entenda o defer em Zig: garanta execução de código de limpeza ao sair de um escopo. Exemplos práticos e armadilhas comuns em pt-BR."
date: "2026-02-21"
author: "Zig Brasil"
---

# Defer em Zig — O que é e Como Usar

Entenda o defer em Zig: garanta execução de código de limpeza ao sair de um escopo. Exemplos práticos e armadilhas comuns em pt-BR.


# Defer em Zig — O que é e Como Usar

## Definição

O **`defer`** em Zig é uma instrução que agenda a execução de um trecho de código para quando o **escopo atual terminar**, independentemente de como ele termina — seja por retorno normal, erro ou qualquer outro fluxo. É o mecanismo principal em Zig para garantir que recursos sejam liberados de forma confiável.

Pense no `defer` como uma promessa: "não importa o que aconteça, execute isso antes de sair daqui".

## Por que Defer Importa

1. **Gerenciamento de recursos**: Garante que memória, arquivos e conexões sejam liberados.
2. **Código mais limpo**: A alocação e a desalocação ficam próximas no código, facilitando a leitura.
3. **Segurança contra erros**: Mesmo que uma função retorne um erro com `try`, o `defer` ainda executa.
4. **Substituição do RAII**: Em Zig não há destrutores automáticos; `defer` cumpre esse papel.

## Exemplo Prático

### Uso Básico

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

pub fn main() !void {
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();  // Executado ao sair de main

    const allocator = gpa.allocator();

    const buffer = try allocator.alloc(u8, 1024);
    defer allocator.free(buffer);  // Liberado mesmo se houver erro abaixo

    // Usar buffer aqui...
    std.debug.print("Buffer alocado com {} bytes\n", .{buffer.len});
}
```

### Múltiplos Defers (Ordem LIFO)

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

pub fn main() void {
    std.debug.print("1: início\n", .{});

    defer std.debug.print("4: último defer (primeiro a executar)\n", .{});
    defer std.debug.print("3: segundo defer\n", .{});
    defer std.debug.print("2: primeiro defer (último a executar)\n", .{});

    std.debug.print("5: fim do escopo\n", .{});
}
// Saída: 1, 5, 4, 3, 2
```

Os defers executam em ordem **LIFO** (Last In, First Out) — como uma pilha. O último `defer` declarado é o primeiro a executar.

### Defer com Arquivo

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

fn lerArquivo(caminho: []const u8) ![]u8 {
    const allocator = std.heap.page_allocator;

    const arquivo = try std.fs.cwd().openFile(caminho, .{});
    defer arquivo.close();  // Fecha o arquivo ao sair da função

    const conteudo = try arquivo.readToEndAlloc(allocator, 1024 * 1024);
    return conteudo;
}
```

Mesmo que `readToEndAlloc` falhe com um erro, o `defer arquivo.close()` garante que o descritor de arquivo será fechado.

## Defer vs Errdefer

| Característica | `defer` | `errdefer` |
|---------------|---------|------------|
| Quando executa | **Sempre** ao sair do escopo | **Apenas** quando há erro |
| Uso típico | Limpeza geral | Desfazer alocação parcial |

```zig
fn criarRecurso(allocator: std.mem.Allocator) !*Recurso {
    const ptr = try allocator.create(Recurso);
    errdefer allocator.destroy(ptr);  // Só libera se o resto falhar

    ptr.* = try inicializar();  // Se isso falhar, errdefer executa
    return ptr;  // Se chegar aqui, errdefer NÃO executa
}
```

## Armadilhas Comuns

- **Usar `defer` dentro de loop**: O defer só executa quando o **escopo** termina, não a cada iteração. Se precisar de limpeza por iteração, use um bloco explícito.
- **Esquecer que defers são LIFO**: Ao trabalhar com dependências (ex: abrir conexão, depois abrir transação), a ordem dos defers é crucial.
- **Captura de variáveis**: O `defer` captura ponteiros, não valores. Se a variável for modificada antes do defer executar, o defer verá o valor modificado.
- **Confundir com `errdefer`**: Use `defer` para limpeza incondicional e `errdefer` para reverter apenas em caso de erro.

## Boas Práticas com Defer

**Coloque o `defer` logo após a aquisição do recurso**: Isso torna a relação entre aquisição e liberação imediatamente óbvia para quem lê o código.

```zig
const conn = try abrirConexao(host);
defer conn.fechar(); // Liberação fica junto da aquisição

const tx = try conn.iniciarTransacao();
defer tx.rollback(); // Se commit não ocorrer, faz rollback
```

**Use blocos com `defer` para limpezas complexas**:

```zig
defer {
    cache.invalidar(chave);
    metricas.decrementar("conexoes_ativas");
    std.log.info("Recurso liberado", .{});
}
```

**Cuidado com `defer` dentro de loops**: O `defer` executa ao sair do bloco que o contém, não a cada iteração. Para limpeza por iteração, use um bloco explícito:

```zig
for (itens) |item| {
    // Bloco cria escopo próprio — defer executa em cada iteração
    {
        const recurso = try adquirir(item);
        defer recurso.liberar();
        try processar(recurso);
    }
}
```

## Comparação com Outras Linguagens

Em C++, o padrão RAII usa destrutores de objetos para liberar recursos automaticamente. Em Go, `defer` existe com comportamento semelhante ao do Zig, mas com diferenças: em Go os argumentos são avaliados no momento da declaração do `defer`, enquanto em Zig o código inteiro roda ao sair do escopo. Em Rust, o `Drop` trait oferece destruição determinística. O `defer` do Zig é mais explícito e previsível que o RAII implícito — você vê claramente o que acontece ao sair de cada escopo.

## Termos Relacionados

- [Errdefer](/glossario/errdefer/) — Defer condicional para erros
- [Error Union](/glossario/error-union/) — Tipo que pode conter erro ou valor
- [RAII em Zig](/glossario/raii-zig/) — Padrão de gerenciamento de recursos
- [Try](/glossario/try/) — Operador de propagação de erros

## Tutoriais Relacionados

- [Tratamento de Erros em Zig](/tutoriais/tratamento-de-erros-em-zig/)
- [Gerenciamento de Memória em Zig](/tutoriais/gerenciamento-de-memoria-zig/)
- [Introdução ao Zig](/tutoriais/introducao-ao-zig/)
