@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
@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
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
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
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
- Serialização JSON/XML: Usar o nome da tag como chave de tipo ao serializar unions para formatos textuais.
- Logging estruturado: Incluir o tipo do evento ou estado em mensagens de log.
- Depuração: Imprimir qual variante está ativa durante investigação de bugs.
- Métricas e telemetria: Categorizar eventos por tipo usando o nome da tag.
- Interface de usuário: Exibir o tipo de um valor union para o usuário em formato legível.
Builtins relacionados
- @errorName — Obtém o nome de um erro como string
- @typeName — Obtém o nome de um tipo
- @intFromEnum — Obtém valor inteiro de um enum
- @typeInfo — Inspeciona tagged unions e enums