switch语句 #
一、switch 基础 #
1.1 基本 switch 语句 #
zig
const std = @import("std");
pub fn main() void {
const day: u8 = 3;
switch (day) {
1 => std.debug.print("Monday\n", .{}),
2 => std.debug.print("Tuesday\n", .{}),
3 => std.debug.print("Wednesday\n", .{}),
4 => std.debug.print("Thursday\n", .{}),
5 => std.debug.print("Friday\n", .{}),
6, 7 => std.debug.print("Weekend\n", .{}),
else => std.debug.print("Invalid day\n", .{}),
}
}
1.2 switch 表达式 #
switch 是表达式,可以返回值:
zig
const std = @import("std");
pub fn main() void {
const day: u8 = 3;
const day_name = switch (day) {
1 => "Monday",
2 => "Tuesday",
3 => "Wednesday",
4 => "Thursday",
5 => "Friday",
6, 7 => "Weekend",
else => "Invalid",
};
std.debug.print("Day: {s}\n", .{day_name});
}
1.3 必须穷尽所有情况 #
zig
const std = @import("std");
pub fn main() void {
const value: u8 = 5;
// 编译错误:没有处理所有情况
// switch (value) {
// 1 => std.debug.print("One\n", .{}),
// 2 => std.debug.print("Two\n", .{}),
// }
// 正确:使用 else 处理剩余情况
switch (value) {
1 => std.debug.print("One\n", .{}),
2 => std.debug.print("Two\n", .{}),
else => std.debug.print("Other\n", .{}),
}
}
二、模式匹配 #
2.1 多值匹配 #
zig
const std = @import("std");
pub fn main() void {
const c: u8 = 'a';
switch (c) {
'a', 'e', 'i', 'o', 'u' => std.debug.print("Vowel\n", .{}),
'A', 'E', 'I', 'O', 'U' => std.debug.print("Uppercase vowel\n", .{}),
'0'...'9' => std.debug.print("Digit\n", .{}),
else => std.debug.print("Other\n", .{}),
}
}
2.2 范围匹配 #
zig
const std = @import("std");
pub fn main() void {
const score: i32 = 85;
const grade = switch (score) {
90...100 => 'A',
80...89 => 'B',
70...79 => 'C',
60...69 => 'D',
0...59 => 'F',
else => '?',
};
std.debug.print("Grade: {c}\n", .{grade});
}
2.3 捕获值 #
zig
const std = @import("std");
pub fn main() void {
const value: u8 = 5;
switch (value) {
0 => std.debug.print("Zero\n", .{}),
1...10 => |v| std.debug.print("Small: {}\n", .{v}),
11...100 => |v| std.debug.print("Medium: {}\n", .{v}),
else => |v| std.debug.print("Large: {}\n", .{v}),
}
}
三、枚举匹配 #
3.1 枚举 switch #
zig
const std = @import("std");
const Color = enum {
red,
green,
blue,
};
pub fn main() void {
const color = Color.green;
const hex = switch (color) {
.red => "#FF0000",
.green => "#00FF00",
.blue => "#0000FF",
};
std.debug.print("Color hex: {s}\n", .{hex});
}
3.2 枚举捕获 #
zig
const std = @import("std");
const Direction = enum {
north,
south,
east,
west,
};
fn getOpposite(dir: Direction) Direction {
return switch (dir) {
.north => .south,
.south => .north,
.east => .west,
.west => .east,
};
}
pub fn main() void {
const dir = Direction.north;
const opposite = getOpposite(dir);
std.debug.print("Original: {}, Opposite: {}\n", .{ dir, opposite });
}
3.3 带数据的枚举 #
zig
const std = @import("std");
const Value = union(enum) {
int: i32,
float: f64,
string: []const u8,
};
pub fn main() void {
const v = Value{ .int = 42 };
switch (v) {
.int => |i| std.debug.print("Integer: {}\n", .{i}),
.float => |f| std.debug.print("Float: {d}\n", .{f}),
.string => |s| std.debug.print("String: {s}\n", .{s}),
}
}
3.4 修改捕获值 #
zig
const std = @import("std");
const Value = union(enum) {
int: i32,
float: f64,
};
pub fn main() void {
var v = Value{ .int = 42 };
switch (v) {
.int => |*i| {
i.* *= 2;
std.debug.print("Doubled: {}\n", .{i.*});
},
.float => |*f| {
f.* *= 2.0;
std.debug.print("Doubled: {d}\n", .{f.*});
},
}
}
四、标签枚举 #
4.1 使用 else 捕获标签 #
zig
const std = @import("std");
const Status = enum {
pending,
approved,
rejected,
cancelled,
};
pub fn main() void {
const status = Status.pending;
switch (status) {
.approved => std.debug.print("Approved!\n", .{}),
.rejected => std.debug.print("Rejected\n", .{}),
else => |s| std.debug.print("Status: {}\n", .{s}),
}
}
4.2 内联 switch #
zig
const std = @import("std");
pub fn main() void {
const values = [_]i32{ 1, 2, 3, 4, 5 };
for (values) |v| {
const result = switch (v) {
1 => "one",
2 => "two",
3 => "three",
else => "other",
};
std.debug.print("{} => {s}\n", .{ v, result });
}
}
五、高级用法 #
5.1 嵌套 switch #
zig
const std = @import("std");
const Opcode = enum {
add,
sub,
mul,
};
const Mode = enum {
immediate,
register,
};
pub fn main() void {
const opcode = Opcode.add;
const mode = Mode.immediate;
switch (opcode) {
.add => {
switch (mode) {
.immediate => std.debug.print("ADD immediate\n", .{}),
.register => std.debug.print("ADD register\n", .{}),
}
},
.sub => {
switch (mode) {
.immediate => std.debug.print("SUB immediate\n", .{}),
.register => std.debug.print("SUB register\n", .{}),
}
},
.mul => {
switch (mode) {
.immediate => std.debug.print("MUL immediate\n", .{}),
.register => std.debug.print("MUL register\n", .{}),
}
},
}
}
5.2 switch 与错误 #
zig
const std = @import("std");
const FileError = error{
NotFound,
PermissionDenied,
TooLarge,
};
pub fn main() void {
const err = FileError.PermissionDenied;
const message = switch (err) {
error.NotFound => "File not found",
error.PermissionDenied => "Permission denied",
error.TooLarge => "File too large",
};
std.debug.print("Error: {s}\n", .{message});
}
5.3 switch 与可选类型 #
zig
const std = @import("std");
pub fn main() void {
const maybe_value: ?i32 = 42;
const result = switch (maybe_value) {
null => "No value",
else => |v| blk: {
break :blk if (v > 10) "Large" else "Small";
},
};
std.debug.print("Result: {s}\n", .{result});
}
六、实战示例 #
6.1 简单计算器 #
zig
const std = @import("std");
const Operator = enum {
add,
sub,
mul,
div,
};
fn calculate(a: f64, op: Operator, b: f64) ?f64 {
return switch (op) {
.add => a + b,
.sub => a - b,
.mul => a * b,
.div => if (b != 0) a / b else null,
};
}
pub fn main() void {
const operations = [_]struct { f64, Operator, f64 }{
.{ 10, .add, 5 },
.{ 10, .sub, 3 },
.{ 10, .mul, 2 },
.{ 10, .div, 0 },
};
for (operations) |op| {
const a, const operator, const b = op;
if (calculate(a, operator, b)) |result| {
std.debug.print("{d} {} {d} = {d}\n", .{ a, operator, b, result });
} else {
std.debug.print("{d} {} {d} = Error\n", .{ a, operator, b });
}
}
}
6.2 状态机 #
zig
const std = @import("std");
const State = enum {
idle,
loading,
success,
error,
};
const Event = enum {
start,
complete,
fail,
reset,
};
fn transition(state: State, event: Event) State {
return switch (state) {
.idle => switch (event) {
.start => .loading,
else => .idle,
},
.loading => switch (event) {
.complete => .success,
.fail => .error,
else => .loading,
},
.success => switch (event) {
.reset => .idle,
else => .success,
},
.error => switch (event) {
.reset => .idle,
else => .error,
},
};
}
pub fn main() void {
var state: State = .idle;
state = transition(state, .start);
std.debug.print("State: {}\n", .{state});
state = transition(state, .complete);
std.debug.print("State: {}\n", .{state});
state = transition(state, .reset);
std.debug.print("State: {}\n", .{state});
}
6.3 JSON 值处理 #
zig
const std = @import("std");
const JsonValue = union(enum) {
null: void,
bool: bool,
int: i64,
float: f64,
string: []const u8,
array: []const JsonValue,
};
fn printJson(value: JsonValue, indent: usize) void {
const spaces = " " ** indent;
switch (value) {
.null => std.debug.print("{s}null\n", .{spaces}),
.bool => |b| std.debug.print("{s}{}\n", .{ spaces, b }),
.int => |i| std.debug.print("{s}{}\n", .{ spaces, i }),
.float => |f| std.debug.print("{s}{d}\n", .{ spaces, f }),
.string => |s| std.debug.print("{s}\"{s}\"\n", .{ spaces, s }),
.array => |arr| {
std.debug.print("{s}[\n", .{spaces});
for (arr) |item| {
printJson(item, indent + 2);
}
std.debug.print("{s}]\n", .{spaces});
},
}
}
pub fn main() void {
const json = JsonValue{ .array = &[_]JsonValue{
.{ .int = 1 },
.{ .string = "hello" },
.{ .bool = true },
} };
printJson(json, 0);
}
七、最佳实践 #
7.1 使用枚举而非魔法数字 #
zig
// 好
const Status = enum {
pending,
running,
completed,
failed,
};
fn handleStatus(status: Status) void {
switch (status) {
.pending => {},
.running => {},
.completed => {},
.failed => {},
}
}
// 避免
fn handleStatusCode(code: u8) void {
switch (code) {
0 => {},
1 => {},
2 => {},
3 => {},
else => {},
}
}
7.2 避免空的 else #
zig
// 好:明确处理每种情况
switch (status) {
.pending => handlePending(),
.running => handleRunning(),
.completed => handleCompleted(),
.failed => handleFailed(),
}
// 避免:空的 else
switch (status) {
.pending => handlePending(),
else => {}, // 可能遗漏重要情况
}
7.3 使用 switch 表达式 #
zig
// 好
const message = switch (status) {
.success => "Operation succeeded",
.failure => "Operation failed",
};
// 避免
var message: []const u8 = undefined;
switch (status) {
.success => message = "Operation succeeded",
.failure => message = "Operation failed",
}
八、总结 #
switch 语句要点:
| 特性 | 说明 |
|---|---|
| 基本语法 | switch (value) { ... } |
| 多值匹配 | 1, 2, 3 => |
| 范围匹配 | 1...10 => |
| 枚举匹配 | .value => |
| 值捕获 | |v| => |
| 表达式 | 可返回值 |
下一步,让我们学习循环语句!
最后更新:2026-03-27