---
title: "Zig para Programadores Swift"
url: "https://ziglang.com.br/artigos/zig-para-programadores-swift/"
markdown_url: "https://ziglang.com.br/artigos/zig-para-programadores-swift.MD"
description: "Guia de Zig para desenvolvedores Swift. Mapeamento de conceitos: optionals, protocolos vs comptime, ARC vs allocators, enums, error handling e mais."
date: "2026-02-21"
author: "Zig Brasil"
---

# Zig para Programadores Swift

Guia de Zig para desenvolvedores Swift. Mapeamento de conceitos: optionals, protocolos vs comptime, ARC vs allocators, enums, error handling e mais.


## Introdução

Se você é desenvolvedor Swift, muitos conceitos de Zig serão familiares. Ambas as linguagens valorizam segurança, optionals explícitos, enums poderosos e tratamento de erros sem exceções tradicionais. A diferença fundamental é que Swift usa ARC (Automatic Reference Counting) e Zig usa alocadores explícitos — o programador gerencia memória manualmente.

Este guia mapeia conceitos de Swift para Zig, facilitando a transição. Para perspectivas de outras linguagens, veja [Zig para Programadores Kotlin](/artigos/zig-para-programadores-kotlin/) e [Zig para Programadores C#](/artigos/zig-para-programadores-csharp/).

## Mapeamento de Conceitos

| Swift | Zig | Notas |
|-------|-----|-------|
| `let x = 42` | `const x: i32 = 42` | Imutável por padrão |
| `var x = 42` | `var x: i32 = 42` | Mutável |
| `Optional<T>` / `T?` | `?T` | Conceito idêntico |
| `protocol` | Comptime duck typing | Sem dispatch dinâmico |
| `enum` | `enum` | Tagged unions similares |
| `struct` (value type) | `struct` | Similar |
| `class` (ref type) | Ponteiro para struct | Manual |
| ARC | Allocators | Diferença fundamental |
| `guard let` | `orelse return` | Similar |
| `if let` | `if (opt) \|val\|` | Unwrap seguro |
| `defer` | `defer` | Idêntico em conceito |
| `throw/catch` | Error unions | Sem exceções |
| Generics | `comptime` | Compilação |
| `String` | `[]const u8` | Bytes UTF-8 |

## Optionals: Surpreendentemente Similar

Optionals em Swift e Zig são quase idênticos em conceito:

### Swift

```swift
let valor: Int? = 42
if let v = valor {
    print("Valor: \(v)")
}
let seguro = valor ?? 0
guard let v = valor else { return }
```

### Zig

```zig
const valor: ?i32 = 42;
if (valor) |v| {
    std.debug.print("Valor: {}\n", .{v});
}
const seguro = valor orelse 0;
const v = valor orelse return;
```

A sintaxe difere, mas a semântica é praticamente a mesma. Ambas as linguagens forçam tratamento explícito de valores opcionais.

## Enums e Tagged Unions

Swift tem enums com associated values. Zig tem tagged unions — conceitualmente o mesmo:

### Swift

```swift
enum Resultado {
    case sucesso(String)
    case erro(Int, String)
    case carregando
}

func processar(_ r: Resultado) {
    switch r {
    case .sucesso(let msg):
        print("OK: \(msg)")
    case .erro(let codigo, let msg):
        print("Erro \(codigo): \(msg)")
    case .carregando:
        print("Carregando...")
    }
}
```

### Zig

```zig
const Resultado = union(enum) {
    sucesso: []const u8,
    erro: struct { codigo: i32, mensagem: []const u8 },
    carregando: void,
};

fn processar(r: Resultado) void {
    switch (r) {
        .sucesso => |msg| std.debug.print("OK: {s}\n", .{msg}),
        .erro => |e| std.debug.print("Erro {}: {s}\n", .{ e.codigo, e.mensagem }),
        .carregando => std.debug.print("Carregando...\n", .{}),
    }
}
```

## Protocolos vs Comptime

### Swift

```swift
protocol Serializavel {
    func serializar() -> Data
    static func deserializar(de data: Data) -> Self
}

struct Usuario: Serializavel {
    let nome: String
    func serializar() -> Data { /* ... */ }
    static func deserializar(de data: Data) -> Usuario { /* ... */ }
}

func salvar<T: Serializavel>(_ item: T) {
    let dados = item.serializar()
    // salvar dados...
}
```

### Zig

```zig
fn salvar(item: anytype) !void {
    const dados = item.serializar();
    // salvar dados...
    _ = dados;
}

// Ou com verificação explícita
fn salvarVerificado(comptime T: type, item: T) !void {
    comptime {
        if (!@hasDecl(T, "serializar")) {
            @compileError("Tipo deve ter método serializar()");
        }
    }
    const dados = item.serializar();
    _ = dados;
}
```

Zig usa "duck typing" em tempo de compilação em vez de protocolos formais. Se o tipo tem o método necessário, funciona. Caso contrário, o compilador gera um erro claro.

## Error Handling

Swift e Zig têm abordagens similares de error handling — ambas evitam exceções tradicionais:

### Swift

```swift
enum ArquivoError: Error {
    case naoEncontrado
    case semPermissao
    case corrompido
}

func lerArquivo(_ caminho: String) throws -> String {
    guard FileManager.default.fileExists(atPath: caminho) else {
        throw ArquivoError.naoEncontrado
    }
    return try String(contentsOfFile: caminho)
}

do {
    let conteudo = try lerArquivo("config.txt")
    print(conteudo)
} catch ArquivoError.naoEncontrado {
    print("Arquivo não encontrado")
}
```

### Zig

```zig
const ArquivoError = error{
    NaoEncontrado,
    SemPermissao,
    Corrompido,
};

fn lerArquivo(allocator: std.mem.Allocator, caminho: []const u8) ![]u8 {
    const arquivo = std.fs.cwd().openFile(caminho, .{}) catch {
        return error.NaoEncontrado;
    };
    defer arquivo.close();
    return arquivo.readToEndAlloc(allocator, 1024 * 1024);
}

const conteudo = lerArquivo(allocator, "config.txt") catch |err| switch (err) {
    error.NaoEncontrado => {
        std.debug.print("Arquivo não encontrado\n", .{});
        return;
    },
    else => return err,
};
defer allocator.free(conteudo);
```

Veja [Error Sets Customizados](/receitas/zig-error-set-customizado/) e [Padrões Errdefer](/receitas/zig-errdefer-pattern/).

## ARC vs Allocators

### Swift

```swift
class MinhaClasse {
    var dados: [Int]
    init() { dados = [] }
    // ARC libera automaticamente quando refcount = 0
}

var obj = MinhaClasse()
var ref = obj  // refcount = 2
ref = MinhaClasse()  // refcount de obj volta para 1
```

### Zig

```zig
const MinhaStruct = struct {
    dados: std.ArrayList(i32),

    pub fn init(allocator: std.mem.Allocator) MinhaStruct {
        return .{ .dados = std.ArrayList(i32).init(allocator) };
    }

    pub fn deinit(self: *MinhaStruct) void {
        self.dados.deinit();
    }
};

var obj = MinhaStruct.init(allocator);
defer obj.deinit(); // VOCÊ é responsável pela liberação
```

Em Zig, não há contagem de referências automática. O padrão `init`/`defer deinit` garante que recursos sejam liberados. Veja [GeneralPurposeAllocator](/receitas/zig-general-purpose-allocator/) e [Detectar Vazamentos de Memória](/receitas/zig-detectar-memory-leak/).

## Closures e Funções

### Swift

```swift
let numeros = [1, 2, 3, 4, 5]
let dobrados = numeros.map { $0 * 2 }
let filtrados = numeros.filter { $0 > 3 }
```

### Zig

```zig
const numeros = [_]i32{ 1, 2, 3, 4, 5 };

// Zig não tem map/filter built-in — usar loops explícitos
var resultado = std.ArrayList(i32).init(allocator);
defer resultado.deinit();

for (numeros) |n| {
    if (n > 3) {
        try resultado.append(n * 2);
    }
}
```

Zig não tem closures com captura de variáveis como Swift. Funções anônimas existem mas não capturam escopo. Isso é intencional — mantém a linguagem previsível em termos de alocações.

## Strings

### Swift

```swift
let nome: String = "Zig Brasil"
let tamanho = nome.count
let maiusculo = nome.uppercased()
let contem = nome.contains("Brasil")
```

### Zig

```zig
const nome: []const u8 = "Zig Brasil";
const tamanho = nome.len; // bytes, não caracteres Unicode
const contem = std.mem.indexOf(u8, nome, "Brasil") != null;

// Para uppercase, iterar manualmente
var buffer: [nome.len]u8 = undefined;
for (nome, 0..) |c, i| {
    buffer[i] = std.ascii.toUpper(c);
}
```

Strings em Zig são slices de bytes (`[]const u8`), não tipos ricos como em Swift. Para manipulações avançadas, veja [Manipulação de Strings](/receitas/zig-concatenar-strings/) e [Converter Maiúsculas e Minúsculas](/receitas/zig-converter-maiusculas-minusculas/).

## Testes

### Swift

```swift
func testSoma() {
    XCTAssertEqual(soma(2, 3), 5)
}
```

### Zig

```zig
test "soma" {
    try std.testing.expectEqual(@as(i32, 5), soma(2, 3));
}
```

Testes em Zig são inline e executados com `zig test`. Veja [Testes Unitários](/receitas/zig-teste-unitario-basico/) e [Testes com Allocator](/receitas/zig-teste-com-allocator/).

## Conclusão

Programadores Swift têm uma vantagem na transição para Zig: os conceitos de optionals, enums com dados associados, e error handling sem exceções são muito similares. A maior adaptação será o gerenciamento manual de memória — trocar ARC por allocators explícitos requer disciplina mas oferece controle total.

Se você está explorando linguagens de sistemas, veja também nosso portal sobre <a href="https://rustlang.com.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'rustlang.com.br' })">Rust</a>, frequentemente comparado a Swift por seu foco em segurança, e sobre <a href="https://kotlin.dev.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'kotlin.dev.br' })">Kotlin</a>, outra linguagem moderna com conceitos familiares.

Para começar, visite [Introdução ao Zig](/tutoriais/introducao-ao-zig/) e [Como Instalar Zig](/tutoriais/como-instalar-zig/). Para entender quando Zig é adequado, leia [Quando Usar Zig](/artigos/quando-usar-zig/).
