Zig 的学习资源比大多数语言少,而且分散。官方文档还不完整,中文资料几乎没有,社区相对小。但 Zig 的语言本身其实不复杂——核心概念就那几个,搞清楚了学起来很快。
这篇文章的目标是给你一条具体的路线:从哪里开始、按什么顺序学、在哪里容易卡住、做什么项目练手。假设你有 Java/Go/Python 背景,没有 C 基础也没关系。
一、学之前:你需要什么基础
有帮助但不是必须的:了解 C 的基本概念——指针、栈和堆的区别、内存手动管理。如果你写过 C 或者 C++,Zig 里的很多设计会立刻感觉熟悉。
真正必须的:能读懂英文技术文档,能接受一门语言不像 Python/Java 那样"帮你做很多事"的设计风格。
Zig 的门槛不在语法,在思维模式的转换:你需要习惯"每一件事都是显式的"。内存从哪里分配?你说了算。错误怎么处理?你必须显式处理。这对习惯了 GC 语言的人来说需要一点适应时间,但不是很长。
一个有用的前置练习:在学 Zig 之前,花一两天写几个 C 程序——一个链表、一个简单的文件读写。不需要写得多好,只是为了建立"我要自己管内存"的意识。
二、学习路线:按这个顺序
第一步:zig.guide(一两天)
从 zig.guide 开始,不要从官方文档开始。官方文档(ziglang.org/documentation)非常详细,但它是参考手册,不是教程,线性读下去会失去方向感。
zig.guide 是目前最好的入门教程,覆盖了语言的主要特性,示例代码可以直接运行,更新频率也较高。用一两天过一遍,重点不是记住所有 API,而是建立对这门语言的整体感觉。
第二步:Ziglings(边做边学)
Ziglings 是一个练习项目——106 个有 bug 的小程序,你的任务是修复它们让测试通过,每道题都有注释提示。覆盖了 Zig 的核心概念,每道题 5-15 分钟能做完。
git clone https://github.com/ratfactor/ziglings
cd ziglings
zig build
做 Ziglings 的方式:不要跳过,按顺序做。碰到卡住的题,先自己想 10 分钟,再看提示,实在不行再看答案——但要确保你理解了答案,而不是复制粘贴过去。
第三步:官方标准库源码
Zig 学习里最被低估的资源是标准库源码本身。标准库用 Zig 写成,代码质量很高,里面有大量真实使用 comptime、分配器、错误处理的例子。
找到你本地的 Zig 安装目录,里面有一个 lib/std/ 文件夹。当你对某个标准库函数的用法不确定时,直接去看它的实现。这比看文档更有用,因为你能看到完整的上下文和边界情况处理。
第四步:做一个真实项目(最重要)
到这一步,你已经有了足够的基础知识,剩下的只能靠写代码来学。
三、三个最值得花时间的概念
Zig 有很多特性,但有三个是学习过程中最容易卡住、也是最值得投入时间的:
1. 分配器:彻底搞懂它
分配器(Allocator)是 Zig 里最陌生的概念。核心是:任何需要动态分配内存的操作,都需要你传入一个分配器。
const std = @import("std");
pub fn main() !void {
// 通用分配器,用于一般场景
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit(); // 程序结束时检测内存泄漏
const allocator = gpa.allocator();
// Arena 分配器:所有分配在 deinit 时一次性释放
var arena = std.heap.ArenaAllocator.init(allocator);
defer arena.deinit();
const arena_alloc = arena.allocator();
// 用 arena 分配器构建一个列表
var list = std.ArrayList(u32).init(arena_alloc);
try list.append(1);
try list.append(2);
// arena.deinit() 会释放 list 的所有内存,不需要手动 list.deinit()
}
学分配器的正确方式是:把四种主要分配器都用一遍——GeneralPurposeAllocator(通用)、ArenaAllocator(竞技场,适合请求/响应这类"批量分配批量释放"的场景)、FixedBufferAllocator(在固定缓冲区上分配,不做任何系统调用,适合嵌入式)、std.testing.allocator(测试专用,自动检测泄漏)。
理解了分配器,你就理解了 Zig 对内存的核心主张:分配的来源和分配的策略是可以独立控制的。
2. comptime:先用,再理解
comptime 概念上不难(在编译期执行普通 Zig 代码),但"什么时候用、能用来做什么"需要一点练习才能建立直觉。
最快的学习路径是:先从泛型函数入手,看明白"类型也是值"这件事:
// T 是编译期参数,类型本身是一等公民
fn Stack(comptime T: type) type {
return struct {
items: []T,
len: usize,
const Self = @This();
pub fn init(allocator: std.mem.Allocator) !Self {
return Self{
.items = try allocator.alloc(T, 16),
.len = 0,
};
}
pub fn push(self: *Self, item: T) void {
self.items[self.len] = item;
self.len += 1;
}
};
}
// 使用:用类型参数实例化
var int_stack = try Stack(i32).init(allocator);
var str_stack = try Stack([]const u8).init(allocator);
理解了"函数可以返回类型"这件事,comptime 的其他用法(条件编译、编译期计算、编译期反射)都是同一个机制的延伸。
3. 错误处理:不要用 catch unreachable 绕过去
Zig 的错误处理机制(错误联合类型 !T、try、catch)设计清晰,但初学者容易用 catch unreachable 或者 catch {} 把错误静默掉,导致程序行为不可预测。
// 不好的写法(掩盖了错误)
const value = someFunction() catch unreachable;
// 好的写法:明确处理每种可能的错误
const value = someFunction() catch |err| switch (err) {
error.OutOfMemory => return error.OutOfMemory, // 向上传播
error.InvalidInput => {
std.debug.print("invalid input, using default\n", .{});
break :blk default_value;
},
};
// 或者简单向上传播
const value = try someFunction();
好的练习是:写一个程序,让它的所有错误路径都有明确的处理,不用任何 unreachable。这会强迫你真正思考"这里会出什么错、我要怎么处理",而不是让错误消失。
四、做什么项目练手
按难度递增,选一个做:
入门(一两天):命令行工具
写一个 wc 的简单实现——统计文件的行数、单词数、字节数。这个项目会让你用到:文件 I/O、字符串处理、标准输出、命令行参数解析。小但完整,Zig 标准库在这些方面支持很好。
./wc myfile.txt
# 输出: 42 lines, 156 words, 2048 bytes
进阶(三五天):HTTP 服务器
用 Zig 的内置 HTTP 服务器(std.http.Server)写一个能响应 GET 请求的简单 HTTP 服务器。这会用到分配器(处理请求需要动态分配缓冲区)、错误处理、并发的基础知识。
中级(一两周):解析器
写一个 JSON 解析器(或者更简单的 CSV 解析器)。解析器是练习 Zig 的好项目,因为它需要精确的内存控制、大量的错误处理、以及 comptime 在某些情况下能带来很好的设计。标准库里有一个 JSON 解析器,可以在写完之后对比看。
五、卡住了怎么办
第一选择:读标准库源码。如果你不知道某个 API 怎么用,找到它的实现,看看标准库里哪里调用了它,模仿那个用法。标准库的测试代码尤其有参考价值——lib/std/xxx_test.zig 里有大量使用示例。
第二选择:Zig Discord 和 Ziggit(论坛)。Zig 社区规模不大但质量高,提问通常能快速得到有帮助的回复。提问时粘上你的代码和编译器报错信息。
第三选择:搜索 GitHub 上的 Zig 项目。找几个用 Zig 写的开源项目(Bun 的 Zig 部分、TigerBeetle 等),看真实项目里怎么组织代码。代码量不用读完,找你不确定的那个具体模式怎么写就够了。
遇到编译器报错看不懂:Zig 的错误信息通常很精确,但对初学者来说格式不够友好。最有用的技巧是:把报错里的关键词(比如具体的类型名)粘进搜索引擎,加上 "zig" 关键词,通常能找到相似的问题讨论。
六、关于版本的注意事项
Zig 目前(2026 年)还是 pre-1.0,每个版本之间有破坏性变更。学习时用 nightly 版本或者最新的稳定版(当前是 0.14.x),不要用旧版本——网上很多教程是旧版本写的,有些代码在新版本里编译不了。
遇到网上的代码示例运行失败,先确认是不是版本问题。查一下 Zig 的 CHANGELOG 或者直接问社区"这段代码在最新版本里怎么写",通常很快能解决。
七、总结
- 顺序:zig.guide → Ziglings → 标准库源码 → 真实项目
- 三个核心概念:分配器(把四种都用一遍)、comptime(从泛型函数入手)、错误处理(不用
unreachable绕过) - 练手项目:wc 命令行工具 → HTTP 服务器 → 解析器
- 卡住时:标准库源码 → Zig Discord → GitHub 上的 Zig 项目
- 版本:用最新版,遇到示例代码失败先检查版本兼容性
Zig 的学习曲线主要来自思维模式的切换,而不是语言的复杂性。一旦习惯了"所有东西都显式"这个设计原则,语言本身是相当一致且可预测的——这也是它值得学的原因之一。