202405
观点/教程
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 作者的又一力作,通过编写一个任务调度器,讲述了多线程编程的基本要领:
- 共享的数据要加锁
条件变量要和锁一起使用,会有虚假唤醒的问题,因此在被唤醒时,需要重新检查状态是否正确。
1 2 3 4 5 6 7 8 9
fn run(self: *Self) void { while (true) { self.mutex.lock(); while (self.queue.peek() == null) { self.cond.wait(&self.mutex); } // TODO } }
它会在 wait 前释放锁,在 wait 返回时先加锁,类似下面的实现:
1 2 3 4 5 6 7 8 9 10 11 12 13
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