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。