观点/教程

Thoughts on Zig

又一篇 Zig 初学者的使用体验文档,如果你也在犹豫要不要学 Zig,这是个不错的经验参考。

I’m sold on Zig’s simplicity : r/Zig

一个具有资深经验开发者,在这里描述了自己选择业余项目语言的经历:

  • Rust 越来越复杂,有种发展成 C++ 的趋势
  • C++ 新版本的特性(比如 module)LSP 支持的不够好,而且历史包袱严重
  • C 缺少元编程,并且没有命名空间

最后从 Andrew 的一个播客了解到 Zig,经过自己尝试,发现了 Zig 没有辜负他的期望,尽管是第一次写 Zig,但基本上没有什么难度, 每次遇到问题,仔细想几分钟就差不多有答案了。下面是他罗列的 Zig 的一些优势:

  • 十分简洁,import 返回的是一个 struct,和其他变量一样使用
  • 与 C 无缝交换,
  • 具有 Result 效果的错误处理
  • 唯一缺失的就是『接口』,但这一点并不是很关键,就像在 C里也没有,但是 C 可以做任何事

Zig’s New CLI Progress Bar Explained

Andrew 的一篇文章,讲述了在最新版的 Zig 中,对进度条的改进实现,现在的进度展示更加友好。

实现的难点在于在多线程环境下,如何保证高性能,文章中大致讲述了其实现:

  • 首先通过预先分配好需要使用的结构,保证后续无需在进行 heap 申请
  • 通过 atomic 操作来实现一个无锁的 freelist,用于申请、释放 Node

Writing a task scheduler in Zig

Openmymind 作者的又一力作,通过编写一个任务调度器,讲述了多线程编程的基本要领:

  • 共享的数据要加锁

  • 条件变量要和锁一起使用,会有虚假唤醒的问题,因此在被唤醒时,需要重新检查状态是否正确。

    fn run(self: *Self) void {
      while (true) {
        self.mutex.lock();
        while (self.queue.peek() == null) {
          self.cond.wait(&self.mutex);
        }
        // TODO
      }
    }
    

    它会在 wait 前释放锁,在 wait 返回时先加锁,类似下面的实现:

    fn wait(c: *std.Thread.Condition, mutex: *std.Thread.Mutex) void {
      // do some setup
      // ...
    
      mutex.unlock();
    
      // whatever happens, we'll always return with this locked
      defer mutex.lock();
    
      // wait for signal
      // or timeout if calling timedWait
      // ...
    }
    

项目/工具

zigar
Enable the use of Zig code in JavaScript project。它可以让你直接在 JS 中调用 zig 代码,背后原理是编译成了 wasm 实现的。

srijan-paul/nez
An emulator for the NES console.

deckarep/ziglang-set
A generic and general purpose Set implementation for the Zig language

akarpovskii/tuile
A Text UI library for Zig

Zig 语言更新