Ziglings 笔记 81: 匿名结构体字面量 (Anonymous Struct Literals)
一次性的快递包
在 Ziglings 的第 81 个练习中,我们遇到了 匿名结构体字面量。
在 C 语言或 Go 语言中,如果你想传一组相关的数据给函数,通常得先定义一个 struct,起个名字,然后实例化它。
但在 Zig 中,如果你只是想“临时”打包几个数据传给函数,根本不需要定义类型。直接用 .{} 就行了!
挑战:无需定义的结构体
我们需要调用 printCircle 函数,传给它一个圆。
但是我们不想费劲去专门定义一个 Circle 类型。我们只想把数据“打包”扔进去。
解决方案
利用 .{} 语法创建字面量,并配合 anytype 接收参数:
const print = @import("std").debug.print;
pub fn main() void {
// 创建一个匿名结构体字面量
// 我们不需要提前定义 struct Circle { ... }
// 直接写出字段名和值即可。
printCircle(.{
// @as 用于显式指定类型,否则默认为 comptime_int
.center_x = @as(u32, 205),
.center_y = @as(u32, 187),
.radius = @as(u32, 12),
});
}
// 接收端:使用 anytype
// 这是一个泛型函数。编译器会检查传入的参数是否有 center_x 等字段。
fn printCircle(circle: anytype) void {
print("x:{} y:{} radius:{}\n", .{
circle.center_x,
circle.center_y,
circle.radius,
});
}
核心知识点总结
1. 语法糖 .{}
这个语法在 Zig 中随处可见。
- 类型推导:如果上下文已知类型(如
const p: Point = .{...}),它就是Point的初始化器。 - 匿名自造:如果上下文未知类型(如本题),它就创建一个全新的、匿名的结构体类型及其实例。
2. 配置模式 (Config Pattern)
这种写法在 Zig 的标准库中常用于传递配置选项。 例如,初始化一个 HTTP 客户端时,你可能会看到:
client.init(.{
.timeout = 5000,
.headers = my_headers
});
这种写法既清晰又灵活,不需要为了一个配置项专门去查阅对应的结构体名字。
3. 编译期求值
值得注意的是,这种匿名结构体字面量通常是在编译期完全求值的。这意味着编译器非常清楚里面有哪些字段,这为各种元编程魔法提供了基础。
后续预告:既然匿名结构体可以打包“命名”的字段(如 .x, .y),那能不能打包“未命名”的字段呢?就像数组那样?答案是肯定的。下一篇我们将学习 元组 (Tuples)。