---
title: "Tagged Union em Zig — O que é e Como Usar"
url: "https://ziglang.com.br/glossario/tagged-union-em-zig-o-que-%C3%A9-e-como-usar/"
markdown_url: "https://ziglang.com.br/glossario/tagged-union-em-zig-o-que-%C3%A9-e-como-usar.MD"
description: "Entenda tagged unions em Zig: unions discriminadas que combinam tipo e valor com segurança. Essenciais para modelar dados variantes. Guia pt-BR."
date: "2026-02-21"
author: "Zig Brasil"
---

# Tagged Union em Zig — O que é e Como Usar

Entenda tagged unions em Zig: unions discriminadas que combinam tipo e valor com segurança. Essenciais para modelar dados variantes. Guia pt-BR.


# Tagged Union em Zig — O que é e Como Usar

## Definição

Uma **tagged union** (union discriminada ou union etiquetada) em Zig é um tipo que pode armazenar **um dentre vários tipos de valor**, junto com uma "tag" (etiqueta) que indica qual variante está ativa no momento. A tag é tipicamente um [enum](/glossario/enum/) e é mantida automaticamente pelo compilador.

Diferentemente de unions em C (que são "burras" e não sabem qual campo está ativo), tagged unions em Zig são **seguras**: o compilador garante que você só acesse o campo correto.

## Por que Tagged Unions Importam

1. **Modelagem de dados variantes**: Representam valores que podem ser de tipos diferentes (ex: token de parser, mensagem de rede).
2. **Segurança**: O compilador impede acesso ao campo errado.
3. **Switch exaustivo**: Obriga tratamento de todas as variantes.
4. **Eficiência**: Ocupam apenas o tamanho do maior campo + a tag.

## Exemplo Prático

### Definição e Uso

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

const Forma = union(enum) {
    circulo: f64,          // raio
    retangulo: struct {
        largura: f64,
        altura: f64,
    },
    triangulo: struct {
        base: f64,
        altura: f64,
    },

    pub fn area(self: Forma) f64 {
        return switch (self) {
            .circulo => |raio| std.math.pi * raio * raio,
            .retangulo => |r| r.largura * r.altura,
            .triangulo => |t| (t.base * t.altura) / 2.0,
        };
    }
};

pub fn main() void {
    const c = Forma{ .circulo = 5.0 };
    const r = Forma{ .retangulo = .{ .largura = 10, .altura = 3 } };

    std.debug.print("Área do círculo: {d:.2}\n", .{c.area()});
    std.debug.print("Área do retângulo: {d:.2}\n", .{r.area()});
}
```

### Switch Exaustivo

```zig
fn descrever(forma: Forma) []const u8 {
    return switch (forma) {
        .circulo => "É um círculo",
        .retangulo => "É um retângulo",
        .triangulo => "É um triângulo",
        // Se você esquecer uma variante, o compilador emite ERRO
    };
}
```

### Tagged Union com Enum Explícito

```zig
const TipoEvento = enum {
    teclado,
    mouse,
    janela,
};

const Evento = union(TipoEvento) {
    teclado: struct { tecla: u32, pressionada: bool },
    mouse: struct { x: i32, y: i32, botao: u8 },
    janela: struct { largura: u32, altura: u32 },
};

fn processarEvento(evento: Evento) void {
    switch (evento) {
        .teclado => |k| {
            if (k.pressionada) {
                std.debug.print("Tecla {} pressionada\n", .{k.tecla});
            }
        },
        .mouse => |m| {
            std.debug.print("Mouse em ({}, {})\n", .{ m.x, m.y });
        },
        .janela => |j| {
            std.debug.print("Janela: {}x{}\n", .{ j.largura, j.altura });
        },
    }
}
```

### Acessando a Tag

```zig
const evento = Evento{ .mouse = .{ .x = 100, .y = 200, .botao = 1 } };

// Acessar a tag como enum
const tag = std.meta.activeTag(evento);
if (tag == .mouse) {
    std.debug.print("É evento de mouse!\n", .{});
}
```

## Armadilhas Comuns

- **Acessar campo inativo**: Tentar ler `.circulo` quando a variante ativa é `.retangulo` causa panic em Debug. Use sempre `switch`.
- **Esquecer variantes no switch**: Sem `else`, o compilador exige exaustividade. Isso é uma **vantagem** — use-a.
- **Confundir com union simples**: `union(enum)` é tagged; `union` sem tag é insegura como em C.
- **Tamanho**: O tamanho da tagged union é o do maior campo + tag. Se um campo for muito maior que os outros, considere usar um ponteiro.

## Casos de Uso

Tagged unions aparecem em diversas situações onde um valor pode ter diferentes formas:

- **Tokens de parser/lexer**: Um token pode ser um número, uma string, um identificador ou um símbolo.
- **Mensagens de sistema**: Eventos de UI, comandos de protocolo, respostas de API.
- **Tipos algébricos**: Implementar `Result<T, E>` ou `Option<T>` do estilo funcional.
- **Nós de AST**: Cada nó de uma árvore sintática abstrata tem um tipo diferente de dado.

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

const Token = union(enum) {
    numero: i64,
    texto: []const u8,
    identificador: []const u8,
    simbolo: u8,
    fim_arquivo,

    pub fn format(self: Token, writer: anytype) !void {
        switch (self) {
            .numero => |n| try writer.print("Num({})", .{n}),
            .texto => |s| try writer.print("Str({s})", .{s}),
            .identificador => |id| try writer.print("Id({s})", .{id}),
            .simbolo => |c| try writer.print("Sym({c})", .{c}),
            .fim_arquivo => try writer.print("EOF", .{}),
        }
    }
};
```

## Comparação com Outras Linguagens

Em C, unions não sabem qual campo está ativo — cabe ao programador manter um campo de "tipo" manualmente, o que é error-prone. Em Rust, o equivalente é o `enum` (que em Rust pode carregar dados, ao contrário de C). Em C++17, há `std::variant`. Zig oferece a mesma segurança que Rust e C++, com sintaxe mais simples e sem overhead de runtime além do tamanho da tag.

A principal vantagem sobre C é que o compilador de Zig emite erro de compilação se você esquecer um caso no `switch`, eliminando bugs silenciosos que surgem quando novas variantes são adicionadas.

## Termos Relacionados

- [Union](/glossario/union/) — Unions simples (sem tag)
- [Enum](/glossario/enum/) — Enumerações
- [Struct](/glossario/struct/) — Tipos estruturados
- [Packed Struct](/glossario/packed-struct/) — Structs com layout exato

## Tutoriais Relacionados

- [Structs, Enums e Unions em Zig](/tutoriais/structs-enums-unions-zig/)
- [Zig Design Patterns](/tutoriais/zig-design-patterns/)
- [Introdução ao Zig](/tutoriais/introducao-ao-zig/)
