---
title: "Perguntas de Entrevista sobre Design Patterns em Zig"
url: "https://ziglang.com.br/entrevistas/perguntas-de-entrevista-sobre-design-patterns-em-zig/"
markdown_url: "https://ziglang.com.br/entrevistas/perguntas-de-entrevista-sobre-design-patterns-em-zig.MD"
description: "Perguntas sobre design patterns e padrões idiomáticos em Zig: allocator pattern, comptime interfaces, error handling patterns, RAII e API design."
date: "2026-02-21"
author: "Zig Brasil"
---

# Perguntas de Entrevista sobre Design Patterns em Zig

Perguntas sobre design patterns e padrões idiomáticos em Zig: allocator pattern, comptime interfaces, error handling patterns, RAII e API design.


# Perguntas de Entrevista sobre Design Patterns em Zig

Design patterns em Zig diferem significativamente dos padrões clássicos de OOP. Zig favorece composição sobre herança, explicitação sobre magia, e simplicidade sobre sofisticação. Entrevistadores de posições seniores avaliam sua capacidade de projetar APIs e arquiteturas idiomáticas em Zig.

## Padrões Idiomáticos de Zig

### Explique o Allocator Pattern.

O padrão mais fundamental de Zig: funções que alocam memória recebem um `Allocator` como parâmetro, tornando alocação explícita e testável. Veja [perguntas de memória](/entrevistas/perguntas-memoria-zig/) para detalhes aprofundados.

```zig
const Parser = struct {
    allocator: std.mem.Allocator,

    pub fn init(allocator: std.mem.Allocator) Parser {
        return .{ .allocator = allocator };
    }

    pub fn parse(self: *Parser, input: []const u8) !Ast {
        const nodes = try self.allocator.alloc(Node, 100);
        errdefer self.allocator.free(nodes);
        // ...
    }
};
```

### Como Zig implementa interfaces/polimorfismo?

Zig não tem interfaces ou classes abstratas. O polimorfismo é alcançado via:

**1. Comptime duck typing (mais idiomático):**
```zig
fn processar(writer: anytype) !void {
    try writer.writeAll("dados");
}
// Aceita qualquer tipo que tenha .writeAll
```

**2. Fat pointers (vtable manual):**
```zig
const Writer = struct {
    ptr: *anyopaque,
    writeFn: *const fn (*anyopaque, []const u8) error{...}!usize,

    pub fn write(self: Writer, data: []const u8) !usize {
        return self.writeFn(self.ptr, data);
    }
};
```

A biblioteca padrão usa esse padrão extensivamente (ex: `std.mem.Allocator`).

### Explique o padrão Init/Deinit.

O equivalente de Zig ao RAII de C++ — explícito e sem magia:

```zig
const Recurso = struct {
    dados: []u8,
    allocator: std.mem.Allocator,

    pub fn init(allocator: std.mem.Allocator) !Recurso {
        return .{
            .dados = try allocator.alloc(u8, 1024),
            .allocator = allocator,
        };
    }

    pub fn deinit(self: *Recurso) void {
        self.allocator.free(self.dados);
    }
};

// Uso:
var r = try Recurso.init(allocator);
defer r.deinit();
```

### O que é o padrão "return error or value" (Builder pattern para erros)?

```zig
fn configurar() !Config {
    var config = Config{};

    config.host = try resolverHost();
    errdefer config.host.deinit();

    config.porta = try lerPorta();
    config.tls = try configurarTLS();
    errdefer config.tls.deinit();

    return config;
}
```

Cada passo pode falhar, e `errdefer` garante cleanup de todos os passos anteriores.

## Padrões de Composição

### Como compor funcionalidade sem herança?

Zig usa composição de structs e embeddings:

```zig
const Logger = struct {
    pub fn log(self: *Logger, msg: []const u8) void { ... }
};

const HttpServer = struct {
    logger: Logger,
    config: Config,

    pub fn handleRequest(self: *HttpServer, req: Request) !Response {
        self.logger.log("Recebida requisição");
        // ...
    }
};
```

### Explique o padrão Sentinel.

Zig usa sentinels para marcar o fim de sequências — similar a null-terminated strings em C, mas generalizado:

```zig
// Slice com sentinel 0
const str: [:0]const u8 = "hello"; // null-terminated
const arr: [5:0]u8 = .{ 1, 2, 3, 4, 5 }; // sentinel 0 após o último
```

Sentinels são verificados em tempo de compilação, eliminando classes de bugs de C.

## Padrões Avançados

### Como implementar o padrão Observer sem herança?

Em Zig, o padrão Observer é implementado com callbacks armazenados em uma lista de function pointers, sem necessidade de classes abstratas:

```zig
const EventoTipo = enum { conectado, desconectado, mensagem_recebida };

const Listener = struct {
    ptr: *anyopaque,
    callbackFn: *const fn (*anyopaque, EventoTipo) void,

    pub fn notificar(self: Listener, evento: EventoTipo) void {
        self.callbackFn(self.ptr, evento);
    }
};

const EventBus = struct {
    listeners: std.ArrayList(Listener),

    pub fn publicar(self: *EventBus, evento: EventoTipo) void {
        for (self.listeners.items) |l| l.notificar(evento);
    }
};
```

Esse padrão é mais explícito que herança virtual: o tamanho da vtable é visível, o overhead é previsível e não há despacho dinâmico oculto.

### O que é o padrão "tagged union" para polimorfismo de dados?

Tagged unions em Zig permitem representar valores de tipos diferentes de forma segura e eficiente:

```zig
const Expressao = union(enum) {
    numero: f64,
    soma: struct { esq: *Expressao, dir: *Expressao },
    produto: struct { esq: *Expressao, dir: *Expressao },

    pub fn avaliar(self: Expressao) f64 {
        return switch (self) {
            .numero => |n| n,
            .soma => |s| s.esq.avaliar() + s.dir.avaliar(),
            .produto => |p| p.esq.avaliar() * p.dir.avaliar(),
        };
    }
};
```

O compilador garante que todos os casos do switch sejam tratados, eliminando a classe de bugs de "case não tratado" comum em linguagens com polimorfismo dinâmico. Este padrão é fundamental para implementar ASTs, parsers e interpretadores em Zig.

## Dicas de Entrevista para Design Patterns

Em entrevistas seniores, as perguntas sobre design patterns em Zig raramente pedem a implementação do padrão em si — elas avaliam se você entende *por que* certos padrões do mundo OOP não se aplicam a Zig e quais são as alternativas idiomáticas. Quando o entrevistador perguntar sobre Singleton, por exemplo, a resposta esperada é que Zig tem variáveis globais explícitas ou constantes de arquivo que servem ao mesmo propósito sem o overhead e a complexidade de uma classe gerenciada. Quando perguntarem sobre Strategy Pattern, mostre como `comptime` e function pointers resolvem o problema de forma mais eficiente e sem despacho dinâmico implícito. Demonstre que você pensa em termos de composição de dados e funções, não de hierarquias de objetos — essa mentalidade é o que separa um desenvolvedor Zig idiomático de alguém que simplesmente traduz código OOP para Zig.

## Preparação

Design patterns são testados em posições seniores. Estude o código-fonte da biblioteca padrão de Zig para exemplos de bons padrões. Combine com [perguntas de error handling](/entrevistas/perguntas-error-handling-zig/), [memória](/entrevistas/perguntas-memoria-zig/) e [comptime](/entrevistas/perguntas-comptime-zig/). Explore o [ecossistema](/ecossistema/) para ver padrões em projetos reais e pratique com [desafios](/entrevistas/desafio-codigo-zig-3/).
