You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何从Zig的可失败函数中返回错误作为值?

在Zig 0.10.1中从可失败函数返回错误作为值

问题原因

你之前写的foo_1和foo_2返回!anyerror类型,但直接返回error.Oops时,Zig会将其识别为函数的错误分支抛出,而非作为anyerror类型的成功值返回。这是因为!T的语义是「要么返回T类型的成功值,要么返回任意错误」,当T本身是anyerror时,Zig会优先把error.Oops判定为错误分支,而非成功的anyerror值。

解决方案

要让错误作为成功值返回,需要明确告诉Zig你要将错误当作anyerror类型的值返回,而非函数的错误分支。有两种常用方式:

方式1:用@as强制类型转换

通过@as明确标注返回值的类型为anyerror,让Zig将其视为成功分支的值:

const std = @import("std");

fn foo() !anyerror {
    return @as(anyerror, error.Oops);
}

fn bar() !void {
    var error_ = try foo();
    std.debug.print("got error: {any}\n", .{ error_ });
}

pub fn main() !void {
    try bar(); // 输出:got error: Oops
}

方式2:用容器类型包装错误

如果需要更清晰的语义,可以用结构体或枚举包装错误,避免类型歧义:

const std = @import("std");

const ErrorValue = struct {
    err: anyerror,
};

fn foo() !ErrorValue {
    return ErrorValue{ .err = error.Oops };
}

fn bar() !void {
    var error_wrapper = try foo();
    std.debug.print("got error: {any}\n", .{ error_wrapper.err });
}

pub fn main() !void {
    try bar(); // 输出:got error: Oops
}

关于错误的嵌套返回

类似可选值的嵌套(如!?i32),错误也可以实现嵌套返回,即使用!!T类型(可失败函数返回另一个可失败类型)。比如:

const std = @import("std");

// 返回类型是!!i32:成功返回!i32类型的值,失败返回任意错误
fn nestedError() !!i32 {
    // 这里返回的是!!i32的成功分支,值为error.Oops(属于!i32类型)
    return error.Oops;
}

fn testNested() !void {
    // try获取!!i32的成功值,得到!i32类型的outer_result
    var outer_result = try nestedError();
    std.debug.print("outer result: {any}\n", .{outer_result}); // 输出:outer result: Oops

    // 对!i32再次使用try,若outer_result是错误则传播,否则获取i32值
    // 这里outer_result是error.Oops,所以try会传播这个错误
    // var inner_value = try outer_result;
}

pub fn main() !void {
    try testNested();
}

需要注意的是,Zig目前(0.10.1)尚未稳定,后续版本的类型语义或语法可能发生变化。

内容的提问来源于stack exchange,提问作者asynts

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 16:37:33