条件语句 #

一、if 基础 #

1.1 基本 if 语句 #

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

pub fn main() void {
    const x: i32 = 10;
    
    if (x > 5) {
        std.debug.print("x is greater than 5\n", .{});
    }
}

1.2 if-else 语句 #

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

pub fn main() void {
    const x: i32 = 3;
    
    if (x > 5) {
        std.debug.print("x is greater than 5\n", .{});
    } else {
        std.debug.print("x is not greater than 5\n", .{});
    }
}

1.3 if-else if-else 链 #

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

pub fn main() void {
    const score: i32 = 85;
    
    if (score >= 90) {
        std.debug.print("Grade: A\n", .{});
    } else if (score >= 80) {
        std.debug.print("Grade: B\n", .{});
    } else if (score >= 70) {
        std.debug.print("Grade: C\n", .{});
    } else if (score >= 60) {
        std.debug.print("Grade: D\n", .{});
    } else {
        std.debug.print("Grade: F\n", .{});
    }
}

二、if 表达式 #

2.1 if 作为表达式 #

在 Zig 中,if 是表达式,可以返回值:

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

pub fn main() void {
    const x: i32 = 10;
    
    const result = if (x > 5) "big" else "small";
    std.debug.print("Result: {s}\n", .{result});
}

2.2 赋值中使用 #

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

pub fn main() void {
    const temperature: i32 = 25;
    
    const status = if (temperature > 30)
        "hot"
    else if (temperature > 20)
        "warm"
    else if (temperature > 10)
        "cool"
    else
        "cold";
    
    std.debug.print("Status: {s}\n", .{status});
}

2.3 块表达式 #

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

pub fn main() void {
    const x: i32 = 10;
    
    const result = if (x > 5) blk: {
        const doubled = x * 2;
        break :blk doubled;
    } else blk: {
        const halved = x / 2;
        break :blk halved;
    };
    
    std.debug.print("Result: {}\n", .{result});
}

三、if 与可选类型 #

3.1 解包可选值 #

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

pub fn main() void {
    const maybe_value: ?i32 = 42;
    
    if (maybe_value) |value| {
        std.debug.print("Got value: {}\n", .{value});
    } else {
        std.debug.print("No value\n", .{});
    }
}

3.2 可选指针解包 #

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

fn findItem(id: u32) ?*Item {
    if (id == 0) return null;
    return &items[id - 1];
}

const Item = struct {
    value: i32,
};

var items = [_]Item{
    .{ .value = 100 },
    .{ .value = 200 },
    .{ .value = 300 },
};

pub fn main() void {
    if (findItem(2)) |item| {
        std.debug.print("Found item with value: {}\n", .{item.value});
        item.value *= 2;
        std.debug.print("Modified value: {}\n", .{item.value});
    } else {
        std.debug.print("Item not found\n", .{});
    }
}

3.3 if 表达式与可选类型 #

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

pub fn main() void {
    const maybe_name: ?[]const u8 = "Zig";
    
    const name = if (maybe_name) |n| n else "Anonymous";
    std.debug.print("Name: {s}\n", .{name});
}

3.4 else if 与可选类型 #

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

fn getEnvVar(name: []const u8) ?[]const u8 {
    if (std.mem.eql(u8, name, "HOME")) return "/home/user";
    if (std.mem.eql(u8, name, "PATH")) return "/usr/bin";
    return null;
}

pub fn main() void {
    const home = getEnvVar("HOME");
    const path = getEnvVar("PATH");
    const shell = getEnvVar("SHELL");
    
    if (home) |h| {
        std.debug.print("HOME: {s}\n", .{h});
    } else if (path) |p| {
        std.debug.print("PATH: {s}\n", .{p});
    } else {
        std.debug.print("No known env vars\n", .{});
    }
    
    if (shell) |s| {
        std.debug.print("SHELL: {s}\n", .{s});
    } else {
        std.debug.print("SHELL not set\n", .{});
    }
}

四、if 与错误联合类型 #

4.1 捕获错误值 #

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

fn divide(a: i32, b: i32) !i32 {
    if (b == 0) return error.DivisionByZero;
    return @divTrunc(a, b);
}

pub fn main() void {
    const result = divide(10, 2);
    
    if (result) |value| {
        std.debug.print("Result: {}\n", .{value});
    } else |err| {
        std.debug.print("Error: {}\n", .{err});
    }
}

4.2 if 表达式与错误 #

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

fn getValue(maybe_error: bool) !i32 {
    if (maybe_error) return error.Failed;
    return 42;
}

pub fn main() void {
    const result = getValue(false);
    
    const message = if (result) |value|
        std.fmt.allocPrint(std.heap.page_allocator, "Success: {}", .{value}) catch "Allocation failed"
    else |err|
        std.fmt.allocPrint(std.heap.page_allocator, "Error: {}", .{err}) catch "Allocation failed";
    
    defer std.heap.page_allocator.free(message);
    std.debug.print("{s}\n", .{message});
}

五、嵌套 if #

5.1 嵌套条件 #

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

pub fn main() void {
    const age: i32 = 25;
    const has_license: bool = true;
    
    if (age >= 18) {
        if (has_license) {
            std.debug.print("Can drive\n", .{});
        } else {
            std.debug.print("Need a license to drive\n", .{});
        }
    } else {
        std.debug.print("Too young to drive\n", .{});
    }
}

5.2 组合条件 #

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

pub fn main() void {
    const age: i32 = 25;
    const has_license: bool = true;
    const has_insurance: bool = true;
    
    if (age >= 18 and has_license and has_insurance) {
        std.debug.print("Fully qualified to drive\n", .{});
    } else if (age >= 18 and has_license) {
        std.debug.print("Can drive but need insurance\n", .{});
    } else if (age >= 18) {
        std.debug.print("Need license and insurance\n", .{});
    } else {
        std.debug.print("Too young\n", .{});
    }
}

六、条件表达式 #

6.1 比较运算符 #

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

pub fn main() void {
    const a: i32 = 10;
    const b: i32 = 20;
    
    std.debug.print("a == b: {}\n", .{a == b});
    std.debug.print("a != b: {}\n", .{a != b});
    std.debug.print("a < b: {}\n", .{a < b});
    std.debug.print("a <= b: {}\n", .{a <= b});
    std.debug.print("a > b: {}\n", .{a > b});
    std.debug.print("a >= b: {}\n", .{a >= b});
}

6.2 逻辑运算符 #

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

pub fn main() void {
    const a = true;
    const b = false;
    
    std.debug.print("a and b: {}\n", .{a and b});
    std.debug.print("a or b: {}\n", .{a or b});
    std.debug.print("!a: {}\n", .{!a});
}

6.3 短路求值 #

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

fn expensiveCheck() bool {
    std.debug.print("Checking...\n", .{});
    return true;
}

pub fn main() void {
    const skip = true;
    
    // and 短路:如果第一个为 false,不评估第二个
    if (skip and expensiveCheck()) {
        std.debug.print("Both true\n", .{});
    }
    
    // or 短路:如果第一个为 true,不评估第二个
    if (skip or expensiveCheck()) {
        std.debug.print("At least one true\n", .{});
    }
}

七、实战示例 #

7.1 输入验证 #

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

const User = struct {
    name: []const u8,
    age: u8,
    email: ?[]const u8,
};

fn validateUser(user: User) !void {
    if (user.name.len == 0) {
        return error.EmptyName;
    }
    
    if (user.age < 18) {
        return error.Underage;
    }
    
    if (user.age > 120) {
        return error.InvalidAge;
    }
    
    if (user.email) |email| {
        if (email.len == 0) {
            return error.EmptyEmail;
        }
        if (std.mem.indexOf(u8, email, "@") == null) {
            return error.InvalidEmail;
        }
    }
}

pub fn main() void {
    const users = [_]User{
        .{ .name = "Alice", .age = 25, .email = "alice@example.com" },
        .{ .name = "", .age = 30, .email = null },
        .{ .name = "Bob", .age = 15, .email = null },
        .{ .name = "Charlie", .age = 200, .email = null },
    };
    
    for (users, 0..) |user, i| {
        validateUser(user) catch |err| {
            std.debug.print("User {}: Validation error - {}\n", .{ i, err });
            return;
        };
        std.debug.print("User {}: Valid\n", .{i});
    }
}

7.2 状态机 #

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

const State = enum {
    idle,
    connecting,
    connected,
    disconnecting,
};

fn handleState(state: State, event: Event) State {
    return switch (state) {
        .idle => if (event == .connect) .connecting else .idle,
        .connecting => if (event == .connected) .connected else if (event == .error) .idle else .connecting,
        .connected => if (event == .disconnect) .disconnecting else .connected,
        .disconnecting => if (event == .disconnected) .idle else .disconnecting,
    };
}

const Event = enum {
    connect,
    connected,
    disconnect,
    disconnected,
    error,
};

pub fn main() void {
    var state: State = .idle;
    
    state = handleState(state, .connect);
    std.debug.print("State: {}\n", .{state});
    
    state = handleState(state, .connected);
    std.debug.print("State: {}\n", .{state});
    
    state = handleState(state, .disconnect);
    std.debug.print("State: {}\n", .{state});
    
    state = handleState(state, .disconnected);
    std.debug.print("State: {}\n", .{state});
}

八、最佳实践 #

8.1 保持条件简单 #

zig
// 好
if (isValid(user)) {
    process(user);
}

// 避免
if (user.name.len > 0 and user.age >= 18 and user.email != null and hasPermission(user)) {
    process(user);
}

8.2 使用早返回 #

zig
// 好
fn process(value: ?i32) !void {
    const v = value orelse return error.NoValue;
    if (v < 0) return error.NegativeValue;
    
    // 处理正常情况
}

// 避免
fn processBad(value: ?i32) !void {
    if (value) |v| {
        if (v >= 0) {
            // 处理正常情况
        } else {
            return error.NegativeValue;
        }
    } else {
        return error.NoValue;
    }
}

8.3 避免深层嵌套 #

zig
// 好:使用早返回
fn processUser(user: ?User) !void {
    const u = user orelse return error.NoUser;
    if (!u.active) return error.InactiveUser;
    if (u.banned) return error.BannedUser;
    
    // 处理正常情况
}

// 避免:深层嵌套
fn processUserBad(user: ?User) !void {
    if (user) |u| {
        if (u.active) {
            if (!u.banned) {
                // 处理正常情况
            } else {
                return error.BannedUser;
            }
        } else {
            return error.InactiveUser;
        }
    } else {
        return error.NoUser;
    }
}

const User = struct {
    active: bool,
    banned: bool,
};

九、总结 #

条件语句要点:

特性 说明
if 语句 基本条件判断
if-else 双分支
if-else if-else 多分支
if 表达式 可返回值
可选解包 if (opt) |v|
错误捕获 if (err) |v| else |e|

下一步,让我们学习 switch 语句!

最后更新:2026-03-27