Zig只有两种变量声明方式:const(不可变)和var(可变)。没有let、mut、static等关键字。
const std = @import("std");
pub fn main() !void {
// const: 不可变绑定(编译器可优化为编译期常量)
const x: i32 = 42;
const y = 100; // 类型推断为 comptime_int
// var: 可变绑定
var counter: usize = 0;
counter += 1;
// 必须初始化!Zig没有未初始化变量
// var z: i32; // 编译错误!
var z: i32 = 0; // 必须给初始值
// undefined: 显式声明未定义值(Debug模式会填充0xAA)
var buf: [1024]u8 = undefined;
// 常量必须在使用前赋值
const computed = x + y;
// 短常量声明(块内)
const sum = add(3, 4);
try std.io.getStdOut().writer().print(
"x={}, y={}, counter={}, sum={}\n",
.{ x, y, counter, sum },
);
}
fn add(a: i32, b: i32) i32 {
return a + b;
}
const变量不能被重新赋值——这是编译错误,不是警告var变量如果声明后未使用会被警告,但const可以(用于类型声明等)undefined是显式的"我知道我在做什么"// 有符号整数: i2 ~ i65535 (2的幂)
const a: i8 = -128; // -128 ~ 127
const b: i32 = -2147483648; // 常见32位
const c: i64 = -1; // 常见64位
const d: i128 = 0; // 128位整数
// 无符号整数: u1 ~ u65535
const e: u8 = 255; // 0 ~ 255, 字节
const f: usize = 0; // 指针大小的无符号整数
const g: u1 = 1; // 1位!只能是0或1
// comptime_int: 编译期任意精度整数
const big = 123456789012345678901234567890;
// 平台相关
const ptr_size = @sizeOf(usize); // 4 或 8
const pi: f16 = 3.141; // 半精度
const e: f32 = 2.718; // 单精度
const phi: f64 = 1.618; // 双精度
const big_f: f80 = 1.0; // 扩展精度(x86)
const huge: f128 = 1.0; // 四精度
// comptime_float: 编译期任意精度浮点
const exact_pi = 3.14159265358979323846;
// 布尔
const t: bool = true;
const f: bool = false;
// 可选类型(类似Rust的Option)
var maybe: ?i32 = 42; // 可以是i32或null
maybe = null; // 可以赋null
// 错误联合类型
var result: anyerror!i32 = 42;
result = error.NotFound;
// 类型本身是一等值
const IntType = i32;
const x: IntType = 42;
// 显式转换——Zig没有隐式类型转换!
const a: i32 = 42;
const b: f64 = @floatFromInt(a); // i32 → f64
const c: i32 = @intFromFloat(b); // f64 → i32 (截断)
const d: u8 = @intCast(a); // i32 → u8 (安全检查)
const e: u32 = @intCast(a); // i32 → u32 (值域检查)
const ptr: *const i32 = &a;
const int_val: usize = @intFromPtr(ptr); // 指针→整数
// 基本函数
fn add(a: i32, b: i32) i32 {
return a + b;
}
// 函数可以返回错误联合类型
fn divide(a: f64, b: f64) !f64 {
if (b == 0.0) return error.DivisionByZero;
return a / b;
}
// 函数可以返回可选类型
fn findItem(items: []const Item, id: u32) ?Item {
for (items) |item| {
if (item.id == id) return item;
}
return null;
}
// defer: 函数退出时执行(类似Go的defer)
fn processFile(path: []const u8) !void {
const file = try std.fs.cwd().openFile(path, .{});
defer file.close(); // 无论如何都关闭
var buf: [1024]u8 = undefined;
const n = try file.readAll(&buf);
// ... 处理buf ...
}
// errdefer: 只在错误返回时执行
fn createResource() !Resource {
const r = try allocateResource();
errdefer freeResource(r); // 只有出错时才释放
if (!initResource(r)) {
return error.InitFailed; // 会触发errdefer
}
return r;
}
// comptime参数:编译期泛型
fn max(comptime T: type, a: T, b: T) T {
return if (a > b) a else b;
}
// 使用
const m1 = max(i32, 3, 7); // 7
const m2 = max(f64, 3.14, 2.71); // 3.14
// if是表达式,有返回值
const abs_x = if (x >= 0) x else -x;
// if + 可选类型解包
if (maybe_value) |val| {
// val 是非null的值
std.debug.print("got: {}\n", .{val});
} else {
std.debug.print("null\n", .{});
}
// while循环
var i: usize = 0;
while (i < 10) : (i += 1) {
// i从0到9
}
// while + 可选类型(类似迭代器)
var it = list.iterator();
while (it.next()) |item| {
// 处理item
}
// for循环(遍历序列)
const items = [_]i32{ 1, 2, 3, 4, 5 };
for (items, 0..) |item, idx| {
std.debug.print("[{}] = {}\n", .{ idx, item });
}
// switch(必须穷举所有情况)
const tag: enum { a, b, c } = .b;
const result = switch (tag) {
.a => "first",
.b => "second",
.c => "third",
};
// 带范围和合并分支的switch
fn classify(n: i32) u8 {
return switch (n) {
0...9 => 1, // 范围
10...99 => 2,
100...999 => 3,
else => 4, // 兜底
};
}
defer和errdefer是Zig资源管理的核心机制:
const std = @import("std");
pub fn main() !void {
// defer: 作用域退出时执行,无论成功还是失败
{
const file = try std.fs.cwd().openFile("test.txt", .{});
defer file.close();
// 无论如何都会close
}
// 多个defer按LIFO顺序执行
{
std.debug.print("1\n", .{});
defer std.debug.print("4\n", .{});
std.debug.print("2\n", .{});
defer std.debug.print("3\n", .{});
std.debug.print("end\n", .{});
// 输出: 1 2 end 3 4
}
// errdefer: 只在错误退出时执行
const result = allocAndInit() catch |err| {
std.debug.print("init failed: {}\n", .{err});
return err;
};
_ = result;
}
fn allocAndInit() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
const allocator = gpa.allocator();
const buf = try allocator.alloc(u8, 1024);
errdefer allocator.free(buf); // 仅出错时释放
// 如果这行失败,errdefer会释放buf
if (!initBuffer(buf)) {
return error.InitFailed;
}
// 成功路径:buf由调用者管理
allocator.free(buf);
}
fn initBuffer(buf: []u8) bool {
@memset(buf, 0xAA);
return true;
}
Zig的内置函数以@开头,提供编译期和运行时的核心操作:
| 函数 | 说明 | 示例 |
|---|---|---|
@import | 导入模块 | @import("std") |
@cImport | 导入C头文件 | @cImport(@cInclude("stdio.h")) |
@sizeOf | 类型大小(字节) | @sizeOf(u64) → 8 |
@alignOf | 类型对齐 | @alignOf(u64) → 8 |
@TypeOf | 获取表达式类型 | @TypeOf(42) → comptime_int |
@intCast | 安全整数转换 | @intCast(i32, x) |
@floatFromInt | 整数转浮点 | @floatFromInt(f64, 42) |
@panic | 不可恢复错误 | @panic("unreachable") |
@compileError | 编译期报错 | @compileError("not impl") |
@setRuntimeSafety | 开关安全检查 | @setRuntimeSafety(false) |
@sizeOf, @alignOf, @bitSizeOff64max(comptime T: type, a: T, b: T) T