我认为是 Pragmatic Programmer 建议你应该每年学习一门新语言。对我来说,2020 年就是 Rust。我阅读了大量有关该语言的书籍,阅读了大量代码并在 Rust 中编写了一些非平凡的代码。这足以让我理解这门语言,我无论如何都不是 Rust 开发人员,但我穿着 Rusty 鞋走了足够长的时间来获得这种感觉。今年,我决定研究 Zig。 Zig 和 Rust 或多或少都在同一个空间中,取代了 C。然而,它们完全不同。 Zig 是一种小语言。我花了几个晚上浏览语言参考,就是这样,我对如何做事有了一个很好的主意。学习曲线大多是平坦的,这是非常巨大的。这尤其是因为我忍不住将 Zig 与 Rust 进行比较。我花了很多精力来理解 Rust,但我几乎没有花任何时间来尝试理解 Zig。这很简单,很明显,也很清楚。在力量方面,请注意,我会在大致相同的位置对两种语言进行评分。你可以用 Zig 写出非常好的代码,只是你不需要把头弯成有趣的形状来让编译器接受你的代码。 Zig 的主要功能之一是它的 comptime 功能。这是一项允许 Zig 在编译时运行代码的功能。这不是一个新的或令人兴奋的特性,老实说,C++ 已经拥有它很多年了。关键区别在于 Zig 可以使用此功能进行代码生成。例如,要创建一个通用列表,您将编写以下代码: 请注意,我们在这里编写了一个返回类型的函数,然后您可以使用该类型。这种方法非常强大,但同时,这很简单,很明显。 Zig 很容易学习,因为在幕后对你隐藏的东西并不多。这实际上导致了 Zig 设计中另一个非常重要的方面。幕后什么都没有。例如,您不能在 Zig 中分配内存,没有全局函数可以为您分配内存。您需要使用分配器来做到这一点。这意味着内存分配可能失败的事实在整个 API、标准库和您的代码中无处不在。没有您需要以某种方式处理的“这在极少数情况下可能会失败”的情况,这很清楚并且在您面前。
同时,Zig 比 C 做了更多的事情来使事情变得更容易。我想集中在几个重要的点上: Zig 有错误的概念。在上面的代码中,函数 push() 可能会因为分配失败而失败。在这种情况下,函数将失败并返回代码。这是由 try 关键字处理的,它将中止当前函数并返回错误。请注意,错误和常规值在 Zig 中是单独的通道(在函数声明中有一个带有 ! 的联合标记)。 Zig 支持 defer 和 errdefer 关键字。 defer 关键字的作用正如您所期望的那样,在函数退出时,它将以相反的顺序运行所有延迟语句。 errdefer 更有趣,因为它只会在函数退出并出现错误时运行。这种看似简单的更改对开发人员需要牢记的代码质量和复杂性产生了巨大影响。 Zig 具有内置测试,以至于 test 是语言中的关键字。给你一些上下文,当我编写 C 代码时,我实际上写了完全相同的东西(手动,使用宏和肮脏)来帮助我完成工作。以同样的方式,分配是显式的并从顶部管理(所有需要分配的类型从其父级获取分配器)这一事实意味着您可以用内存做一些非常酷的事情。很容易说“这段代码只有 10MB 的内存”,然后让它这样运行。我认为,它还最终创建了一个更强大的软件系统,因此内存分配的发生并不罕见,它们一直在发生。总的来说,Zig 感觉 C 好多了,没有额外的心理开销。与 Rust 相比,您几乎可以立即开始工作并且编译速度非常好,以至于您实际上不需要考虑它。 Rust 让你从一开始就感受到缓慢的编译成本,基本上,随着你的系统变得越来越大,这一点很明显。
考虑到这一点,我实际上觉得我们应该将 Zig 与围棋进行比较,因为它在概念上更接近我认为围棋想要成为的样子。事实上,看看人们对围棋最常见的抱怨,Zig 回答了所有问题。顺便说一句,语言可以实现语言服务器并获得自动 IDE 支持这一事实令人惊讶。例如,您还可以在 VS Code 中调试 Zig 代码,几乎没有比本地代码更多的问题。 Zig 是在 LLVM 之上实现的,并从中获得了很多好处。当我看着我从包裹里拿出来的东西时,一直在我脑海中闪过的一件事是:站在巨人的肩膀上。