从 ziggit 这件小事说起
看到 ziggit 这个项目,很容易冒出一句玩笑话:“Zig 现在真是什么都想重写。”不少人重新开始打量的,其实就是一类老问题:旧的底层工具,是否终于有条件换一种方式重做。
这股“重写冲动”到底从哪来
ziggit 的 README 很直白:它把自己定义成一个“用纯 Zig 写的现代 git 实现”,目标是作为 git 的 drop-in replacement 来使用,还强调了更快的执行速度、更小的 WebAssembly 体积,以及面向 LLM agent 的 succinct mode。更重要的是,它要求的构建环境并不重,只需要 Zig 0.15.2+。
它吸引的,主要是那些长期运行在命令行、操作系统边缘和开发者工作流深处的工具。ziggit 的存在说明,已经有人认真算过这笔账,并且认为用 Zig 从头做一套这种级别的底层工具是划算的。
以前很多人一想到跨平台编译、构建脚本、依赖分发、C 互操作和二进制交付,重做旧工具的念头就先冷了。Zig 的价值,不是把这些问题变没,而是把最劝退人的那几层成本往下压了一截。
让人上头的,是整条交付链
Zig 官网首页对自己的定义很克制:它是一门“用于维护健壮、高效和可重用软件的通用编程语言和工具链”。这里最要紧的是 toolchain 这个词。编译器、跨平台能力、zig build、zig cc / zig c++,以及渐进式接入 C/C++ 代码库的能力,都尽量被收进同一个入口里。
zig cc hello.c -target aarch64-linux-musl -O ReleaseFast
zig build -Dtarget=x86_64-windows
很多时候,团队最讨厌的,并不是旧代码本身,而是围着旧代码长出来的构建和发布负担。语言讨论常常停在语法、类型系统和 benchmark,但真正每天磨人的,往往是构建脚本、目标平台、依赖树、release 工具和 CI 参数。Zig 把这些问题尽量提前收进工具里,这一点很难不让人多看一眼。
flowchart LR
A["旧底层工具"] --> B["构建碎片"]
A --> C["跨平台难"]
A --> D["分发很重"]
A --> E["C 资产难动"]
B --> F["重写不划算"]
C --> F
D --> F
E --> F
G["Zig"] --> H["zig build"]
G --> I["交叉编译"]
G --> J["C ABI"]
G --> K["单一二进制"]
H --> L["重写开始值得算账"]
I --> L
J --> L
K --> L
Zig 写起来为什么有一种“很硬”的清爽感
Zig 最出名的设计口号有两句:No hidden control flow 和 No hidden allocations。这两句基本概括了它的气质。
官方 Overview 和 Why Zig 页面反复拿这个做对照。Zig 不要宏,不要预处理器,不要操作符重载,也不鼓励那种“看起来像字段访问,背后其实绕了一圈”的能力。它也不把堆分配悄悄塞进语言层。要分配内存,就显式给 Allocator;要处理失败,就显式处理错误;要在释放路径上兜底,就用 defer 和 errdefer。
这种风格最直接的效果,是代码更容易审计。你读一段 Zig,不太需要先猜“这里是不是偷偷做了分配”“这个调用会不会隐式抛异常”“这个库在背后接管了多少运行时行为”。它当然不保证代码自动变简单,但会让复杂度更容易暴露出来。这也是它适合底层工具、数据库、终端、编译辅助工具和嵌入式程序的原因。
下面这类函数签名,很能代表它的日常风格:pub fn readFileAlloc(allocator: std.mem.Allocator, path: []const u8) ![]u8。责任划分很直白:
- 谁负责分配内存,是调用者传进来的
allocator。 - 可能失败,所以返回的是错误联合类型
![]u8。 - 真正的系统行为在
readFileAlloc里,不靠运行时偷偷替你兜底。
它最现实的优点,是不要求你一把梭重写
Zig 可以渐进接入现有项目。官方 “Why Zig” 页反复强调的是,它想竞争的对象首先是 C。它强调 conform to the C ABI,强调可以把 Zig 模块嵌入现有工程,也强调哪怕项目主体还是 C/C++,你也能先把构建系统换掉。
- 先把
make/cmake/autotools的一部分构建逻辑迁到zig build。 - 先把跨平台编译入口改成
zig cc或zig c++。 - 再把某个边界清楚、适合单独编译的模块改写成 Zig。
- 最后才决定,值不值得继续扩大范围。
所以 Zig 更常出现在“工具重写”的讨论里。工具边界更清楚,也更适合逐步替换。很多团队最先用上的,是 zig build 和整套跨平台交付能力。真正落地时,往往也是先把交付链理顺,再决定要不要把语言层一起迁过去。
C 互操作才是 Zig 最锋利的那把刀
把 Zig 当成“另一门系统语言”来理解,很容易低估它。它最锋利的地方,是它没有要求你先把 C 世界整个丢掉。保留现有 C 库、继续用头文件、继续沿着原有 native 边界工作,只替换最痛的部分,这才是 Zig 最现实的采用路径。所以它给人的感觉更接近一种工程手段,而不是一次性搬家的宣言。
看一圈现在用 Zig 的项目,味道会更明显
如果只谈语言哲学,Zig 很容易被讲成“更克制的 Rust”或者“更现代的 C”。但真看一圈现在用它做东西的项目,会发现它吸引的是一类很具体的产品。
ziggit 是最直观的例子。它面对的是一个老牌 CLI 工具:协议复杂、文件格式固定、用户习惯强、性能敏感、平台兼容要求高。Zig 适合这种项目,因为它天生就站在“轻二进制、跨平台、少依赖、系统边界清楚”这一边。
再看 Bun,它的 README 直接写明:这个 all-in-one 的 JavaScript/TypeScript 工具箱,底层 runtime 是用 Zig 写的。这里最值得注意的,不只是速度,还在于 Zig 很适合承担“启动快、内存占用敏感、最后要打成一个单一可执行文件”的产品核心。
Ghostty 也很有代表性。它把自己定义成 fast、native、feature-rich terminal emulator,同时还把 libghostty 暴露成一个零依赖的 C 和 Zig 库。这非常像 Zig 最擅长的方向:既要跑得快,又要贴近平台,还要能被别的系统继续嵌入。Ghostty 的开发文档甚至会提醒 tip 版本可能需要不同版本的 Zig,这也提醒你,Zig 还在快速进化。
TigerBeetle 则把另一面展示得更彻底。它在官方文档里解释为什么选 Zig 时,强调的是 simple, straightforward code、静态内存分配和 correctness。数据库、存储引擎、复制协议、日志系统这种东西,对语言的要求本来就不只落在“写起来爽不爽”,更落在资源模型能不能说清楚,错误路径能不能验证,二进制和运行时能不能牢牢抓在手里。Zig 默认就站在这一边。
Zig 官方 2024 年写过一篇文章,介绍他们把 ziglang.org 从 Hugo 迁到了一个名叫 Zine 的静态站点生成器上,而 Zine 本身就是用 Zig 写的。它不如数据库和终端那么硬核,但也说明 Zig 不只适合写贴着硬件跑的程序。只要一个工具强调数据流清楚、构建快、依赖少、部署简单,Zig 就有发挥空间。
把这些项目放在一起看,Zig 擅长处理的是这一类工程问题。
所谓“重写一切”,其实是“终于可以把旧链路一起重做”
Zig 的优势很清楚。它提供的是一组会互相放大的能力:
- 语言层面足够小,足够直接,隐式行为少。
- 工具链层面自带编译、构建、交叉编译和 C/C++ 入口。
- 交付层面容易做出单一二进制和多平台产物。
- 迁移层面允许从现有 C/C++ 代码库边缘切入,不需要强迫一次性全盘迁徙。
这几件事叠在一起,很多旧项目才第一次出现“值得重做”的感觉。以前重写一门语言之外,还得顺手重写一整圈工程负担;Zig 的作用就在这里。
代价也别美化,它现在还远没到轻松模式
Zig 现在的上升势头是真实的,但它的限制也同样真实。下载页显示,截至 2026 年 4 月 4 日,最新 stable 是 0.15.2,发布日期是 2025 年 10 月 11 日;同时还挂着 0.16.0-dev 的 master 快照,日期是 2026 年 3 月 9 日。这已经足够说明它还在高速演进。
官方 0.15.1 release notes 也没有遮掩这件事:breaking API changes 很多,非平凡项目的使用者往往需要直接参与演进过程。再加上生态规模还不大、很多库和工作流还没到“闭眼拿来”的程度,Zig 现在仍然更适合愿意承担额外工程责任的团队。
所以 Zig 的门槛不只是语法门槛,更是责任门槛。比较稳妥的引入方式,是先找一块最能体现 Zig 优势的边界,例如跨平台 CLI、本地工具、卡在旧构建系统里的 native 模块,或者有清楚 ABI 边界的小组件。
如果真要评估它,问四个问题就够了:你们最痛的点到底在哪里;有没有一块边界足够小的模块能先试;团队里有没有人愿意啃 allocator、错误路径和 ABI;就算试验最后不继续,过程中沉淀的构建和边界知识值不值得这笔投入。
Zig 和 Rust 到底是什么关系
很多讨论一上来就把 Zig 和 Rust 摆成正面对撞,这种看法太粗了。Rust 的核心卖点,是用更严格的类型系统和所有权模型,把很多内存错误提前拦在编译期;Zig 更强调可读、可控、可渐进接入现有原生生态,也更强调工具链统一。
粗略地分,Rust 先给你更强的静态护栏,也带来更重的规则体系;Zig 先把语言和工具链做直,把责任更多留给你自己承担。所以别把 Zig 理解成“Rust 的平替”。它们会在一些场景里竞争,但优化的成本结构并不一样:
- 如果你最怕的是内存错误和并发错误,且愿意承受更强的语言约束,Rust 往往更占优。
- 如果你最怕的是构建碎片、交付复杂度、平台摩擦和与现有 C/C++ 资产的断层,Zig 会显得非常迷人。
谁最值得现在就去学 Zig
如果你本来就在下面这些方向上工作,Zig 现在就值得认真学:
- 命令行工具、编译辅助工具、包管理器、开发者工作流工具。
- 终端、原生桌面组件、嵌入式软件、系统接口层。
- 数据库、存储引擎、日志系统、网络协议栈这类基础设施核心。
- 已经有一批 C/C++ 代码,希望逐步改善构建和分发体验的团队。
反过来,如果你的工作主要是 Web 业务、B 端后台、普通 SaaS、表单和数据流转系统,那 Zig 当然也能学,但它未必是你现在最该投入的生产语言。因为这类项目的主要瓶颈,通常不在二进制分发、交叉编译和资源模型,而在产品迭代速度、业务建模和团队协作效率。
Zig 的价值,在于它会让某些事突然顺很多。
flowchart TB
A["现在学 Zig"] --> B["CLI / 工具链"]
A --> C["终端 / 原生组件"]
A --> D["数据库 / 存储"]
A --> E["嵌入式 / 系统层"]
A --> F["普通 Web 业务"]
B --> G["优先投入"]
C --> G
D --> G
E --> G
F --> H["先当观察项"]
最后把话收回来
Zig 不负责“重写一切”。它吸引人的地方,在于把一整套原本分散的底层工作重新收拢到了更顺手的工程路径里。
它会让人想重写旧工具,但范围很清楚:Zig 今天最适合的,是一类对可控性、轻量分发和系统边界特别敏感的软件。把这条边界看清,比喊“重写一切”重要得多。
更新附注
- 版本:v1.1
更新日期:2026-04-04 更新原因:补记本轮全站文风整改的版本附注,确认该稿已纳入统一风格收口与横向复看台账。
还没有评论,你可以写下第一条。