Zig 的四个月
Zig 的设计权衡——显式内存管理、可插拔分配器以及新的 IO 接口——在与 Rust、C++、Go 和 Odin 的比较中,既赢得了系统程序员的赞赏,也引发了怀疑。评论者称赞 Zig 的控制力、可组合接口以及以性能优先的 “TigerStyle” 思路,但也批评它频繁的破坏性变更、较弱的错误上下文传递、对底层库的重新实现,以及诸如对编译期特性的 IDE 支持不足等工具链缺口。许多人最终认为,Zig 适合专门的高性能或嵌入式场景,但还不是对更成熟生态系统的明确通用替代品。
错误处理与诊断
- 有人强调 Rust 的
?运算符和基于From的错误组合很强大,但也“很别扭”,往往需要自定义错误类型或辅助 crate。 - Zig 的错误集被认为更简单、更“内建”,但它们并不会自然携带丰富上下文或嵌套;保留详细诊断通常需要更多手工工作。
- 有人认为 Zig 的模型会鼓励丢弃有用的调试信息;也有人喜欢这种简单性,并认为额外上下文应由开发者显式负责。
分配器、arena 与对内存的控制
- 在库代码和系统代码中,Zig 的显式分配器模型获得了强烈支持:调用方始终掌控,代码可以在受限或自定义环境中运行,并且避免了全局分配器。
- Arena 因按生命周期分组分配而受到称赞(例如按每个 HTTP 请求划分),它能减少碎片、避免逐对象释放,并限制内存使用上限。
- 批评者指出,若生命周期判断失误,arena 可能泄漏;它们并不总比调优过的 malloc 更快;而且会让可增长结构更复杂;他们认为 Zig 的“到处传分配器”模式相比 RAII/GC 更啰嗦,也更脆弱。
- 关于在数据结构中存储分配器(Odin 风格)还是每次调用时传入分配器的争论:权衡在于运行时内存开销与调用点噪音之间的取舍,以及分配器不匹配的风险。
异步与 IO 接口
- 早期“无色 async”尝试被批评为隐式化;当前 Zig 的设计使用显式 IO 接口,带有动态分发,并可选择阻塞或异步后端。
- 有人认为这仍然是“隐藏的魔法”,因为同一个 API 背后行为可能变化;也有人坚持这只是库层面的间接层,不是编译器魔法,而且文档已经完整说明。
TigerStyle 与性能思维
- TigerStyle(先从硬件角度设计)在一些人看来大多是常识,而且如果不做剖析很难完美应用。
- 也有人认为它对大型系统和架构比对修复局部热点更重要;不过,仍有几位指出 TigerBeetle 极其特殊的约束限制了其普适性。
标准库、平台 API 与安全性
- Zig 重新实现 libc、crypto、compression,并使用底层 Windows NT API 而不是官方 Win32 表面,这些做法被批评为有风险,而且与杀毒软件的预期不兼容。
- 支持者说 NT API 更干净,也更像 Unix,有助于跨平台代码;怀疑者则认为这些选择削弱了人们对 Zig 作为“严肃”生产语言的信心。
稳定性、易用性与工具
- 频繁的破坏性变更(例如 IO 接口的演进)是一个重大痛点,尤其对大型项目而言。
- 对
comptime代码缺乏稳健的 IDE 支持和自动补全,被一些人视为不可接受。 - 总体而言,Zig 在低层、高控制领域表现出色,但许多参与者在通用应用和依赖工具链较重的工作上更偏好 Rust/Go。