@errorName em Zig — Referência e Exemplos

@errorName em Zig

O @errorName retorna o nome de um valor de erro como uma string legível. É uma ferramenta essencial para depuração, logging e mensagens de erro amigáveis. Em Zig, erros são valores de primeira classe, e este builtin permite converter esses valores para suas representações textuais.

Sintaxe

@errorName(err: anyerror) [:0]const u8

O que faz

O @errorName recebe um valor de erro e retorna seu nome como uma string de bytes constante terminada em sentinela nulo. O nome retornado corresponde exatamente ao identificador usado na declaração do error set.

Parâmetros

  • err (anyerror): Um valor de erro de qualquer error set. Deve ser um erro concreto, não um error union (!T).

Valor de retorno

Retorna [:0]const u8 — uma string terminada em zero contendo o nome do erro.

Exemplos práticos

Exemplo 1: Logging de erros

const std = @import("std");

const ArquivoErro = error{
    NaoEncontrado,
    PermissaoNegada,
    DiskCheio,
    Corrompido,
};

fn abrirArquivo(caminho: []const u8) ArquivoErro!void {
    _ = caminho;
    return ArquivoErro.NaoEncontrado;
}

test "logging de erros" {
    const resultado = abrirArquivo("/tmp/teste.txt");
    if (resultado) |_| {
        // Sucesso
    } else |err| {
        const nome = @errorName(err);
        std.debug.print("Erro ao abrir arquivo: {s}\n", .{nome});
        // Saída: "Erro ao abrir arquivo: NaoEncontrado"
        try std.testing.expectEqualStrings("NaoEncontrado", nome);
    }
}

Exemplo 2: Sistema de logging estruturado

const std = @import("std");

const NivelLog = enum { debug, info, warn, err };

fn log(nivel: NivelLog, mensagem: []const u8, erro_opt: ?anyerror) void {
    const prefixo = switch (nivel) {
        .debug => "[DEBUG]",
        .info => "[INFO]",
        .warn => "[WARN]",
        .err => "[ERRO]",
    };

    if (erro_opt) |err| {
        std.debug.print("{s} {s} (erro: {s})\n", .{
            prefixo,
            mensagem,
            @errorName(err),
        });
    } else {
        std.debug.print("{s} {s}\n", .{ prefixo, mensagem });
    }
}

test "logging estruturado" {
    log(.info, "Servidor iniciado", null);
    log(.err, "Falha na conexão", error.ConnectionRefused);
    log(.warn, "Tentativa de acesso negada", error.PermissaoNegada);
}

Exemplo 3: Tradução de erros para mensagens amigáveis

const std = @import("std");

const DbErro = error{
    ConexaoPerdida,
    TabelaNaoExiste,
    ChaveDuplicada,
    TimeoutConsulta,
};

fn mensagemAmigavel(err: DbErro) []const u8 {
    return switch (err) {
        error.ConexaoPerdida => "A conexão com o banco de dados foi perdida. Tente novamente.",
        error.TabelaNaoExiste => "A tabela solicitada não foi encontrada no banco de dados.",
        error.ChaveDuplicada => "Já existe um registro com essa chave. Use um valor diferente.",
        error.TimeoutConsulta => "A consulta demorou demais. Tente uma consulta mais simples.",
    };
}

fn tratarErroDb(err: DbErro) void {
    // Mensagem técnica para logs
    std.debug.print("DB Error: {s}\n", .{@errorName(err)});

    // Mensagem amigável para o usuário
    std.debug.print("Mensagem: {s}\n", .{mensagemAmigavel(err)});
}

test "mensagens de erro" {
    tratarErroDb(error.ConexaoPerdida);
    tratarErroDb(error.ChaveDuplicada);
}

Casos de uso comuns

  1. Logging e monitoramento: Registrar o nome do erro em logs para diagnóstico e análise de incidentes.
  2. Mensagens de erro para o usuário: Exibir o nome técnico do erro junto com uma mensagem amigável.
  3. Serialização de erros: Converter erros para strings ao transmitir via rede (APIs, RPC).
  4. Depuração: Imprimir erros durante o desenvolvimento para entender fluxos de execução.
  5. Telemetria: Enviar nomes de erros para sistemas de monitoramento e alertas.

Observações

  • O @errorName funciona com qualquer error set, incluindo anyerror.
  • A string retornada é estática e válida durante toda a execução do programa.
  • Não há operação inversa direta (string para erro) disponível como builtin. Para isso, seria necessário implementar manualmente usando @typeInfo.

Builtins relacionados

  • @tagName — Obtém o nome do campo ativo de uma tagged union
  • @typeName — Obtém o nome de um tipo como string
  • @typeInfo — Inspeciona error sets e outros tipos
  • @compileError — Gera erro de compilação personalizado

Tutoriais relacionados

Continue aprendendo Zig

Explore mais tutoriais e artigos em português para dominar a linguagem Zig.