---
title: "@tagName em Zig — Referência e Exemplos"
url: "https://ziglang.com.br/builtins/@tagname-em-zig-refer%C3%AAncia-e-exemplos/"
markdown_url: "https://ziglang.com.br/builtins/@tagname-em-zig-refer%C3%AAncia-e-exemplos.MD"
description: "Referência completa do @tagName em Zig. Aprenda a obter o nome do campo ativo de unions e enums com exemplos práticos."
date: "2026-02-21"
author: "Zig Brasil"
---

# @tagName em Zig — Referência e Exemplos

Referência completa do @tagName em Zig. Aprenda a obter o nome do campo ativo de unions e enums com exemplos práticos.


# @tagName em Zig

O `@tagName` retorna o nome do campo ativo de uma tagged union ou o nome de uma variante de enum como string. É fundamental para serialização, logging e depuração de código que trabalha com unions e enums.

## Sintaxe

```zig
@tagName(valor: anytype) [:0]const u8
```

## O que faz

O `@tagName` recebe um valor de enum ou tagged union e retorna o nome do campo/variante ativo como uma string constante terminada em sentinela nulo. Para enums, retorna o nome da variante atual. Para tagged unions, retorna o nome do campo ativo.

## Parâmetros

- **valor** (`anytype`): Um valor de tipo enum ou tagged union. O tipo deve ter campos nomeados — unions sem tag não são aceitas.

## Valor de retorno

Retorna `[:0]const u8` — uma string terminada em zero com o nome do campo ou variante ativo.

## Exemplos práticos

### Exemplo 1: Nome de variantes de enum

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

const Estacao = enum { primavera, verao, outono, inverno };

test "tag name de enum" {
    const estacao = Estacao.verao;
    const nome = @tagName(estacao);

    try std.testing.expectEqualStrings("verao", nome);

    // Funciona com todas as variantes
    try std.testing.expectEqualStrings("primavera", @tagName(Estacao.primavera));
    try std.testing.expectEqualStrings("inverno", @tagName(Estacao.inverno));
}
```

### Exemplo 2: Serialização de tagged union

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

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

fn serializarForma(forma: Forma, writer: anytype) !void {
    try writer.print("{{\"tipo\": \"{s}\"", .{@tagName(forma)});

    switch (forma) {
        .circulo => |raio| {
            try writer.print(", \"raio\": {d}", .{raio});
        },
        .retangulo => |ret| {
            try writer.print(", \"largura\": {d}, \"altura\": {d}", .{
                ret.largura,
                ret.altura,
            });
        },
        .triangulo => |tri| {
            try writer.print(", \"base\": {d}, \"altura\": {d}", .{
                tri.base,
                tri.altura,
            });
        },
    }
    try writer.writeAll("}");
}

test "serializar forma" {
    var buffer: [256]u8 = undefined;
    var stream = std.io.fixedBufferStream(&buffer);
    const writer = stream.writer();

    const forma = Forma{ .circulo = 5.0 };
    try serializarForma(forma, writer);

    const saida = stream.getWritten();
    try std.testing.expectEqualStrings("{\"tipo\": \"circulo\", \"raio\": 5}", saida);
}
```

### Exemplo 3: Logging de eventos com tagged union

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

const Evento = union(enum) {
    conexao: struct { ip: []const u8, porta: u16 },
    desconexao: struct { motivo: []const u8 },
    mensagem: struct { remetente: []const u8, conteudo: []const u8 },
    erro: struct { codigo: u32, descricao: []const u8 },
};

fn logEvento(evento: Evento) void {
    std.debug.print("[EVENTO:{s}] ", .{@tagName(evento)});

    switch (evento) {
        .conexao => |c| std.debug.print("{s}:{}\n", .{ c.ip, c.porta }),
        .desconexao => |d| std.debug.print("Motivo: {s}\n", .{d.motivo}),
        .mensagem => |m| std.debug.print("De {s}: {s}\n", .{ m.remetente, m.conteudo }),
        .erro => |e| std.debug.print("Código {}: {s}\n", .{ e.codigo, e.descricao }),
    }
}

test "log de eventos" {
    logEvento(.{ .conexao = .{ .ip = "192.168.1.1", .porta = 8080 } });
    logEvento(.{ .mensagem = .{ .remetente = "Alice", .conteudo = "Olá!" } });
    logEvento(.{ .erro = .{ .codigo = 500, .descricao = "Erro interno" } });
}
```

## Casos de uso comuns

1. **Serialização JSON/XML**: Usar o nome da tag como chave de tipo ao serializar unions para formatos textuais.
2. **Logging estruturado**: Incluir o tipo do evento ou estado em mensagens de log.
3. **Depuração**: Imprimir qual variante está ativa durante investigação de bugs.
4. **Métricas e telemetria**: Categorizar eventos por tipo usando o nome da tag.
5. **Interface de usuário**: Exibir o tipo de um valor union para o usuário em formato legível.

## Comportamento em comptime

`@tagName` pode ser usado em tempo de compilação quando o valor é conhecido em comptime. Isso permite construir strings e tabelas de despacho baseadas em variantes de enum sem overhead em runtime:

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

const Operacao = enum { soma, subtracao, multiplicacao, divisao };

// Mapa de nomes em comptime (sem alocação em runtime)
const NOMES_PT = blk: {
    var mapa: [std.meta.fields(Operacao).len][]const u8 = undefined;
    mapa[@intFromEnum(Operacao.soma)] = "Soma";
    mapa[@intFromEnum(Operacao.subtracao)] = "Subtração";
    mapa[@intFromEnum(Operacao.multiplicacao)] = "Multiplicação";
    mapa[@intFromEnum(Operacao.divisao)] = "Divisão";
    break :blk mapa;
};

fn nomePortugues(op: Operacao) []const u8 {
    return NOMES_PT[@intFromEnum(op)];
}
```

## Internacionalização e mapeamento de nomes

`@tagName` retorna o nome exato do identificador em Zig (inglês ou sem acentos). Para exibição ao usuário em português, use `@tagName` como chave interna e mantenha um mapeamento separado:

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

const StatusPedido = enum { pendente, processando, enviado, entregue, cancelado };

fn labelStatus(status: StatusPedido) []const u8 {
    return switch (status) {
        .pendente    => "Aguardando confirmação",
        .processando => "Em processamento",
        .enviado     => "A caminho",
        .entregue    => "Entregue com sucesso",
        .cancelado   => "Pedido cancelado",
    };
}

fn logStatus(status: StatusPedido) void {
    // @tagName para logs internos (inglês, sem espaços)
    std.log.info("status_changed tag={s} label={s}", .{
        @tagName(status),
        labelStatus(status),
    });
}
```

## Desempenho

`@tagName` compila para uma lookup em uma tabela de strings embutida no binário. O custo em runtime é equivalente a um acesso de array indexado pelo valor inteiro do enum/tag — O(1). Não há alocação de memória, pois as strings são constantes estáticas.

## Comparação com equivalente em C

Em C, obter o nome de um enum como string requer código manual:

```c
// C: boilerplate manual e propenso a erros de sincronização
typedef enum { PENDENTE, PROCESSANDO, ENVIADO } Status;

const char* nome_status(Status s) {
    switch (s) {
        case PENDENTE:    return "PENDENTE";
        case PROCESSANDO: return "PROCESSANDO";
        case ENVIADO:     return "ENVIADO";
        default:          return "DESCONHECIDO";
    }
}
```

Em Zig, `@tagName` elimina completamente esse boilerplate — o compilador mantém os nomes automaticamente:

```zig
// Zig: sem boilerplate
const nome = @tagName(status); // sempre sincronizado com o enum
```

## Erros comuns

**1. Usar `@tagName` em unions sem tag:**
```zig
// ERRO de compilação: @tagName requer tagged union ou enum
const UnionSemTag = union {
    a: u32,
    b: f32,
};
var u: UnionSemTag = .{ .a = 1 };
// _ = @tagName(u); // erro!

// CORRETO: usar tagged union (union(enum))
const UnionComTag = union(enum) {
    a: u32,
    b: f32,
};
```

**2. Assumir que `@tagName` retorna string com encoding específico:** A string retornada é ASCII (identificadores Zig são ASCII), então não há preocupação com encoding, mas não espere caracteres especiais ou acentos.

## Perguntas Frequentes

**P: `@tagName` funciona com enums que têm valores inteiros explícitos?**

R: Sim. O valor inteiro não afeta o nome retornado. `@tagName` retorna o nome do identificador, independentemente do valor associado:

```zig
const Codigo = enum(u8) { ok = 200, nao_encontrado = 404, erro = 500 };
// @tagName(Codigo.nao_encontrado) == "nao_encontrado"
```

**P: Posso usar `@tagName` com `std.meta.stringToEnum` para conversão bidirecional?**

R: Sim! `std.meta.stringToEnum(MeuEnum, nome)` faz a operação inversa — converte uma string para o valor de enum correspondente. Juntos, permitem serialização/desserialização simples de enums.

**P: O que acontece com variantes de enum geradas por `@typeInfo` e `inline for`?**

R: `@tagName` funciona normalmente com qualquer valor de enum válido, independentemente de como foi obtido. Iteração sobre campos via `@typeInfo` e uso de `@tagName` é um padrão comum para serialização genérica.

## Builtins relacionados

- [@errorName](/builtins/error-name/) — Obtém o nome de um erro como string
- [@typeName](/builtins/type-name/) — Obtém o nome de um tipo
- [@intFromEnum](/builtins/int-from-enum/) — Obtém valor inteiro de um enum
- [@typeInfo](/builtins/type-info/) — Inspeciona tagged unions e enums

## Tutoriais relacionados

- [Unions em Zig](/tutoriais/unions/)
- [Enums em Zig](/tutoriais/enums/)
- [Serialização em Zig](/tutoriais/serializacao/)
