Errores

Un conjunto de errores es similar a un enum (los detalles sobre los enums de Zig se verán más adelante), donde cada error en el conjunto es un valor. No hay excepciones en Zig; los errores son valores. Vamos a crear un conjunto de errores.

const FileOpenError = error{
    AccessDenied,
    OutOfMemory,
    FileNotFound,
};

Los conjuntos de errores se coercen a sus superconjuntos

const AllocationError = error{OutOfMemory};

test "coerción de error de un subconjunto a un superconjunto" {
    const err: FileOpenError = AllocationError.OutOfMemory;
    try expect(err == FileOpenError.OutOfMemory);
}

Un tipo de conjunto de errores y otro tipo pueden combinarse con el operador ! para formar un tipo de unión de errores. Los valores de estos tipos pueden ser un valor de error o un valor del otro tipo.

Creemos un valor de un tipo de unión de errores. Aquí se usa catch, seguido de una expresión que se evalúa cuando el valor precedente es un error. El catch aquí se usa para proporcionar un valor de respaldo, pero también podría ser un noreturn - el tipo de return, while (true) y otros.

fn failingFunction() error{Oops}!void {
    return error.Oops;
}

test "devolviendo un error" {
    failingFunction() catch |err| {
        try expect(err == error.Oops);
        return;
    };
}

try x es un atajo para x catch |err| return err, y se utiliza comúnmente cuando no es apropiado manejar un error. El try y catch de Zig no están relacionados con try-catch en otros lenguajes.

fn failFn() error{Oops}!i32 {
    try failingFunction();
    return 12;
}

test "try" {
    const v = failFn() catch |err| {
        try expect(err == error.Oops);
        return;
    };
    try expect(v == 12); // nunca se alcanza
}

errdefer funciona como defer, pero solo se ejecuta cuando la función se devuelve con un error dentro del bloque de errdefer’s.

var problems: u32 = 98;

fn failFnCounter() error{Oops}!void {
    errdefer problems += 1;
    try failingFunction();
}

test "errdefer" {
    failFnCounter() catch |err| {
        try expect(err == error.Oops);
        try expect(problems == 99);
        return;
    };
}

Las uniones de errores devueltas desde una función pueden tener sus conjuntos de errores inferidos al no tener un conjunto de errores explícito. Este conjunto de errores inferido contiene todos los errores posibles que la función puede devolver.

fn createFile() !void {
    return error.AccessDenied;
}

test "inferred error set" {
    // La coerción de tipo se lleva a cabo con éxito
    const x: error{AccessDenied}!void = createFile();

    // Zig no nos permite ignorar las uniones de errores mediante _ = x;
    // debemos desenvolverlo con "try", "catch" o "if" de alguna manera
    _ = x catch {};
}

Los conjuntos de errores pueden fusionarse.

const A = error{ NotDir, PathNotFound };
const B = error{ OutOfMemory, PathNotFound };
const C = A || B;

anyerror es el conjunto de errores global, que al ser el superconjunto de todos los conjuntos de errores, puede tener un error de cualquier conjunto coercido a él. Su uso debe evitarse en general.

Edita esta pagina Última actualización: 5/15/2024 por Vital