From de4db967f503355e2d8cfba5674a57a1bc5894c3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Apr 2026 03:23:27 +0000 Subject: [PATCH 1/3] Initial plan From 54d0e0442f3c9e5db9157a89ac6239197f8d5934 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Apr 2026 03:29:49 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=E7=BF=BB=E8=AF=91=EF=BC=9AZig=20=E5=88=9D?= =?UTF-8?q?=E4=BD=93=E9=AA=8C=20(Zig:=20First=20Impressions)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agent-Logs-Url: https://github.com/zigcc/zigcc.github.io/sessions/9cb799f8-8bc4-41fc-add2-517200190e6e Co-authored-by: jiacai2050 <3848910+jiacai2050@users.noreply.github.com> --- .../post/2026-04-16-zig-first-impressions.smd | 244 ++++++++++++++++++ 1 file changed, 244 insertions(+) create mode 100644 content/post/2026-04-16-zig-first-impressions.smd diff --git a/content/post/2026-04-16-zig-first-impressions.smd b/content/post/2026-04-16-zig-first-impressions.smd new file mode 100644 index 0000000..c474d54 --- /dev/null +++ b/content/post/2026-04-16-zig-first-impressions.smd @@ -0,0 +1,244 @@ +--- +.title = "Zig 初体验", +.date = @date("2026-04-16T10:00:00+0800"), +.author = "copilot (翻译)", +.layout = "post.shtml", +.draft = false, +.custom = { + .ai_generated = true, +}, +--- + +> 原文:https://deplet.ing/zig-first-impressions/ + +## [前言]($heading.id('preface')) + +我已经编程很多年了,主要使用 C、Python 和 Go。最近,我开始听说 Zig 这门语言,它的核心理念是"没有隐藏的控制流,没有隐藏的内存分配"。带着好奇心,我花了几周时间上手 Zig,这是我的一些初步感受。 + +## [为什么是 Zig?]($heading.id('why-zig')) + +Zig 是一门系统级编程语言,目标是成为 C 的现代替代品。它既不像 Rust 那样强调内存安全的编译时保证,也不像 Go 那样拥有垃圾回收器。Zig 选择了一条中间道路:给予程序员完整的控制权,同时提供比 C 更好的工具来减少错误。 + +让我感兴趣的特性主要有以下几点: + +- **显式内存管理**:所有内存分配必须显式传递分配器(allocator),没有全局堆操作 +- **comptime**:强大的编译时计算能力,可以在编译期运行任意 Zig 代码 +- **跨平台交叉编译**:内置支持,无需额外工具链 +- **C 互操作**:可以直接 `@import` C 头文件 + +## [上手体验]($heading.id('getting-started')) + +安装 Zig 非常简单。从[官网](https://ziglang.org/download/)下载预编译的二进制文件,解压,加入 `PATH` 即可。不需要安装额外的运行时或虚拟机。 + +第一个程序当然是经典的 Hello World: + +```zig +const std = @import("std"); + +pub fn main() void { + std.debug.print("Hello, World!\n", .{}); +} +``` + +用 `zig run hello.zig` 即可运行。构建速度非常快,第一次运行大约一两秒,后续因为缓存更快。 + +## [语法印象]($heading.id('syntax-impressions')) + +Zig 的语法乍看之下有些奇特,但很快就会习惯。几个显著特点: + +**没有隐式类型转换**。所有类型转换必须显式进行: + +```zig +const x: i32 = 5; +const y: f64 = @floatFromInt(x); // 必须显式转换 +``` + +**变量默认不可变**。用 `const` 声明常量,用 `var` 声明变量: + +```zig +const immutable = 42; +var mutable: i32 = 10; +mutable += 1; +``` + +**没有 `null`,用可选类型代替**。可选类型用 `?T` 表示: + +```zig +fn maybeNull() ?i32 { + return null; // 或者 return 42; +} + +const result = maybeNull() orelse 0; // 提供默认值 +``` + +这种设计强迫你在使用可能为空的值时必须显式处理 null 情况,避免了空指针解引用。 + +## [错误处理]($heading.id('error-handling')) + +Zig 的错误处理是我最喜欢的特性之一。它使用"错误联合类型"(error union),语法是 `!T`: + +```zig +const FileError = error{ + FileNotFound, + PermissionDenied, +}; + +fn openFile(path: []const u8) FileError![]u8 { + if (path.len == 0) return error.FileNotFound; + // ... +} + +pub fn main() !void { + const content = try openFile("config.txt"); + // 或者 + const content2 = openFile("config.txt") catch |err| { + std.debug.print("Error: {}\n", .{err}); + return; + }; + _ = content; + _ = content2; +} +``` + +`try` 关键字会在出错时自动返回错误,类似 Go 的 `if err != nil { return err }`,但更简洁。`catch` 则允许你处理特定错误或提供 fallback。 + +这种方式让错误处理既明确又不繁琐,比 C 的返回码清晰,比 Rust 的 `Result` 简洁(虽然原理相似)。 + +## [内存管理与分配器]($heading.id('memory-management')) + +Zig 最独特的设计之一就是分配器(allocator)系统。在 Zig 中,标准库中几乎所有需要堆分配的函数都要求你传入一个分配器: + +```zig +const std = @import("std"); + +pub fn main() !void { + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + defer _ = gpa.deinit(); + const allocator = gpa.allocator(); + + var list = std.ArrayList(i32).init(allocator); + defer list.deinit(); +} +``` + +起初这显得有些啰嗦,但你很快就会明白其价值: + +1. **可测试性**:测试时可以用 `std.testing.allocator`,它会自动检测内存泄漏 +2. **灵活性**:可以为不同场景选择不同的分配策略,比如竞技场分配器(arena allocator)用于一次性批量分配 +3. **显式性**:代码读者能立刻知道"这里有堆分配" + +## [comptime:编译时计算]($heading.id('comptime')) + +`comptime` 是 Zig 最强大也最独特的特性。它允许在编译期运行任意 Zig 代码,实现泛型、代码生成等功能: + +```zig +fn Vec(comptime T: type, comptime size: usize) type { + return struct { + data: [size]T, + + pub fn init() @This() { + return .{ .data = std.mem.zeroes([size]T) }; + } + }; +} + +const Vec3f = Vec(f32, 3); +const Vec4i = Vec(i32, 4); +``` + +类型本身就是值,可以在编译时传递、计算和返回。这避免了 C++ 模板的复杂性,也不需要 Rust 那样的 trait 系统就能实现泛型。 + +初次接触这个概念时我很困惑,但当我意识到"编译时和运行时代码用的是同一种语言"时,一切都豁然开朗了。 + +## [构建系统]($heading.id('build-system')) + +Zig 内置了构建系统,通过 `build.zig` 文件描述构建过程,本身也是 Zig 代码: + +```zig +const std = @import("std"); + +pub fn build(b: *std.Build) void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const exe = b.addExecutable(.{ + .name = "my-app", + .root_source_file = b.path("src/main.zig"), + .target = target, + .optimize = optimize, + }); + + b.installArtifact(exe); +} +``` + +运行 `zig build` 即可编译。内置支持交叉编译,只需指定 `-Dtarget=aarch64-linux` 等参数,无需安装额外的交叉编译工具链。 + +## [C 互操作]($heading.id('c-interop')) + +Zig 与 C 的互操作是其核心特性之一。你可以直接导入 C 头文件: + +```zig +const c = @cImport({ + @cInclude("stdio.h"); + @cInclude("stdlib.h"); +}); + +pub fn main() void { + _ = c.printf("Hello from C!\n"); +} +``` + +Zig 也可以作为 C 编译器使用(`zig cc`),这意味着你可以用它来编译现有的 C/C++ 项目,并且利用其内置的 musl 等 libc 实现来生成静态链接的可执行文件。 + +## [让我印象深刻的地方]($heading.id('highlights')) + +经过几周的使用,有几点让我特别印象深刻: + +**1. 错误信息质量很高** + +Zig 的编译器错误信息通常很清晰,直接指出问题所在并给出建议。虽然还不及 Rust,但远好于 C/C++。 + +**2. 工具链的一体化** + +`zig` 这个二进制文件集成了编译器、构建系统、包管理器、C 编译器、格式化工具等,不需要像 C++ 项目那样折腾 CMake、Conan 等各种工具的组合。 + +**3. 调试构建自动检查** + +在调试模式下,Zig 会自动检查整数溢出、越界访问等问题,而不是静默地产生未定义行为。这在开发阶段非常有用。 + +**4. 零成本抽象** + +`comptime` 和内联函数让你可以写出高度抽象的代码,编译后与手写的低级代码性能相当。 + +## [遇到的挑战]($heading.id('challenges')) + +当然,上手过程也有不少挑战: + +**语言仍在演进**。Zig 还未到 1.0,API 变化较频繁。我在查阅一些网上的教程时,发现许多代码因为版本差异已经无法编译。建议始终参考与你所用版本对应的官方文档。 + +**学习曲线**。`comptime` 的概念虽然强大,但初学时确实需要一些时间才能真正理解。与此类似,分配器系统起初感觉繁琐。 + +**生态系统较小**。相比 Rust 或 Go,Zig 的第三方库数量还比较少。对于很多需求,你可能需要直接使用 C 库。 + +**文档还不够完善**。标准库的文档相比其他语言来说还比较稀疏,很多时候需要直接读源码。 + +## [总结]($heading.id('conclusion')) + +Zig 是一门令人耳目一新的语言。它没有试图做所有事情,而是专注于做好一件事:提供比 C 更好的系统级编程体验,同时保持简单性和可预测性。 + +如果你: +- 在做系统编程或嵌入式开发 +- 想要一个现代的 C 替代品,但不需要 Rust 的复杂性 +- 对编译时元编程感兴趣 +- 需要与 C 代码深度互操作 + +那么 Zig 值得认真考虑。 + +对于我自己,我打算继续深入学习 Zig,可能会用它重写一些之前用 C 写的小工具。语言的哲学理念——显式优于隐式、没有隐藏的控制流——与我的编程价值观非常契合。 + +相关资源: +- [Zig 官网](https://ziglang.org/) +- [Zig 语言参考](https://ziglang.org/documentation/master/) +- [ziglearn.org](https://ziglearn.org/) +- [Zig 标准库源码](https://github.com/ziglang/zig/tree/master/lib/std) From 1946face0ca760326993888af3b003cf9a1280cd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 16 Apr 2026 03:56:13 +0000 Subject: [PATCH 3/3] =?UTF-8?q?=E7=BF=BB=E8=AF=91=E6=96=87=E7=AB=A0?= =?UTF-8?q?=E6=94=B9=E4=B8=BA=20dev.to/nw229=20=E7=89=88=E6=9C=AC=EF=BC=8C?= =?UTF-8?q?=E6=9B=B4=E6=96=B0=E5=8E=9F=E6=96=87=E9=93=BE=E6=8E=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Agent-Logs-Url: https://github.com/zigcc/zigcc.github.io/sessions/5dfd903d-b114-4092-98d3-211375c7d378 Co-authored-by: jiacai2050 <3848910+jiacai2050@users.noreply.github.com> --- .../post/2026-04-16-zig-first-impressions.smd | 260 ++++++++++-------- 1 file changed, 149 insertions(+), 111 deletions(-) diff --git a/content/post/2026-04-16-zig-first-impressions.smd b/content/post/2026-04-16-zig-first-impressions.smd index c474d54..7d33300 100644 --- a/content/post/2026-04-16-zig-first-impressions.smd +++ b/content/post/2026-04-16-zig-first-impressions.smd @@ -9,28 +9,34 @@ }, --- -> 原文:https://deplet.ing/zig-first-impressions/ +> 原文:https://dev.to/nw229/zig-first-impressions-3f5p ## [前言]($heading.id('preface')) -我已经编程很多年了,主要使用 C、Python 和 Go。最近,我开始听说 Zig 这门语言,它的核心理念是"没有隐藏的控制流,没有隐藏的内存分配"。带着好奇心,我花了几周时间上手 Zig,这是我的一些初步感受。 +最近我一直在学习 Zig。作为一名使用 C、C++ 和 Rust 多年的开发者,每当一门新的系统编程语言出现,我都会忍不住去试一试。Zig 承诺提供 C 级别的性能,同时拥有比 C 更好的安全性,以及比 Rust 更简单的学习曲线。这些听起来很有吸引力,于是我花了一些时间亲自体验了一番。 -## [为什么是 Zig?]($heading.id('why-zig')) +## [什么是 Zig?]($heading.id('what-is-zig')) -Zig 是一门系统级编程语言,目标是成为 C 的现代替代品。它既不像 Rust 那样强调内存安全的编译时保证,也不像 Go 那样拥有垃圾回收器。Zig 选择了一条中间道路:给予程序员完整的控制权,同时提供比 C 更好的工具来减少错误。 +Zig 是一门系统级编程语言,由 Andrew Kelley 创建,目标是成为 C 的现代替代品。它的核心设计理念包括: -让我感兴趣的特性主要有以下几点: +- **没有隐藏的控制流**:没有运算符重载,没有异常,没有析构函数——你看到什么,执行的就是什么 +- **没有隐藏的内存分配**:标准库的函数不会在你不知情的情况下进行堆分配 +- **可选类型取代 null**:消除了整类空指针解引用的 bug +- **错误作为值**:错误处理被集成进类型系统,不再是事后补丁 -- **显式内存管理**:所有内存分配必须显式传递分配器(allocator),没有全局堆操作 -- **comptime**:强大的编译时计算能力,可以在编译期运行任意 Zig 代码 -- **跨平台交叉编译**:内置支持,无需额外工具链 -- **C 互操作**:可以直接 `@import` C 头文件 +## [安装与工具链]($heading.id('installation')) -## [上手体验]($heading.id('getting-started')) +安装 Zig 出乎意料地简单。从[官网](https://ziglang.org/download/)下载对应平台的压缩包,解压,把 `zig` 二进制文件加入 `PATH` 即可。整个过程不超过五分钟。 -安装 Zig 非常简单。从[官网](https://ziglang.org/download/)下载预编译的二进制文件,解压,加入 `PATH` 即可。不需要安装额外的运行时或虚拟机。 +```bash +# 验证安装 +zig version +# 0.14.0 +``` + +这和安装 Rust(需要 rustup、cargo 等)相比,简洁许多。`zig` 这个二进制文件本身就包含了编译器、构建系统、包管理器和格式化工具,是一个真正的"全家桶"。 -第一个程序当然是经典的 Hello World: +## [Hello, World!]($heading.id('hello-world')) ```zig const std = @import("std"); @@ -40,119 +46,172 @@ pub fn main() void { } ``` -用 `zig run hello.zig` 即可运行。构建速度非常快,第一次运行大约一两秒,后续因为缓存更快。 +用 `zig run hello.zig` 运行。第一次会编译,后续有缓存,速度很快。 + +第一个让我感到不适应的地方:`std.debug.print` 的第二个参数是一个匿名结构体字面量 `.{}`,用于传递格式参数。这种写法在 Zig 中随处可见,一开始觉得奇怪,习惯后感觉很统一。 -## [语法印象]($heading.id('syntax-impressions')) +## [语法特点]($heading.id('syntax')) -Zig 的语法乍看之下有些奇特,但很快就会习惯。几个显著特点: +### 类型系统 -**没有隐式类型转换**。所有类型转换必须显式进行: +Zig 是强静态类型语言,没有任何隐式类型转换。所有转换必须显式: ```zig -const x: i32 = 5; -const y: f64 = @floatFromInt(x); // 必须显式转换 +const x: i32 = 42; +const y: i64 = x; // 编译错误! +const z: i64 = @intCast(x); // 正确:显式转换 ``` -**变量默认不可变**。用 `const` 声明常量,用 `var` 声明变量: +这初看是负担,实际上消除了一大类因为隐式转换引发的 bug,尤其是整数截断。 + +### 可选类型与空值安全 + +Zig 没有 `null` 关键字,取而代之的是可选类型 `?T`: ```zig -const immutable = 42; -var mutable: i32 = 10; -mutable += 1; +fn findUser(id: u32) ?User { + if (id == 0) return null; + return User{ .id = id }; +} + +const user = findUser(42) orelse return; +// 或者 +if (findUser(42)) |u| { + std.debug.print("Found: {}\n", .{u.id}); +} ``` -**没有 `null`,用可选类型代替**。可选类型用 `?T` 表示: +编译器强制你在使用可选值之前处理 null 情况,这从根源上杜绝了空指针解引用。 + +### defer + +`defer` 关键字让资源清理变得优雅: ```zig -fn maybeNull() ?i32 { - return null; // 或者 return 42; -} +const file = try std.fs.cwd().openFile("data.txt", .{}); +defer file.close(); // 函数返回时自动执行,无论是否出错 -const result = maybeNull() orelse 0; // 提供默认值 +const data = try file.readToEndAlloc(allocator, 1024 * 1024); +defer allocator.free(data); ``` -这种设计强迫你在使用可能为空的值时必须显式处理 null 情况,避免了空指针解引用。 +和 Go 的 `defer` 类似,但 Zig 的 `defer` 是按照 LIFO 顺序在当前块(block)结束时执行,而不是函数结束时——这个区别很重要。 ## [错误处理]($heading.id('error-handling')) -Zig 的错误处理是我最喜欢的特性之一。它使用"错误联合类型"(error union),语法是 `!T`: +这是我最喜欢 Zig 的地方之一。错误是值,有自己的类型: ```zig -const FileError = error{ - FileNotFound, - PermissionDenied, +const MyError = error{ + OutOfMemory, + InvalidInput, + Overflow, }; -fn openFile(path: []const u8) FileError![]u8 { - if (path.len == 0) return error.FileNotFound; - // ... +fn divide(a: i32, b: i32) MyError!i32 { + if (b == 0) return error.InvalidInput; + return @divExact(a, b); } pub fn main() !void { - const content = try openFile("config.txt"); - // 或者 - const content2 = openFile("config.txt") catch |err| { - std.debug.print("Error: {}\n", .{err}); - return; + const result = try divide(10, 2); + std.debug.print("Result: {d}\n", .{result}); + + // 处理特定错误 + const r2 = divide(10, 0) catch |err| switch (err) { + error.InvalidInput => { + std.debug.print("Cannot divide by zero\n", .{}); + return; + }, + else => return err, }; - _ = content; - _ = content2; + _ = r2; } ``` -`try` 关键字会在出错时自动返回错误,类似 Go 的 `if err != nil { return err }`,但更简洁。`catch` 则允许你处理特定错误或提供 fallback。 +`try` 是 `catch |err| return err` 的语法糖,让错误向上传播变得简洁。`catch` 则可以捕获并处理错误。 -这种方式让错误处理既明确又不繁琐,比 C 的返回码清晰,比 Rust 的 `Result` 简洁(虽然原理相似)。 +与 Go 相比,不需要写烦人的 `if err != nil`;与 Rust 相比,也不需要 `?` 运算符和大量 `match`——两者取了个折中,但我觉得 Zig 的方案更直观。 -## [内存管理与分配器]($heading.id('memory-management')) +## [内存管理:分配器(Allocator)]($heading.id('allocator')) -Zig 最独特的设计之一就是分配器(allocator)系统。在 Zig 中,标准库中几乎所有需要堆分配的函数都要求你传入一个分配器: +Zig 最独特的设计之一是显式分配器系统。任何可能进行堆分配的函数,都需要你传入一个分配器: ```zig const std = @import("std"); pub fn main() !void { + // 通用分配器,会在 deinit 时检测内存泄漏 var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer _ = gpa.deinit(); const allocator = gpa.allocator(); + // 分配一个动态数组 var list = std.ArrayList(i32).init(allocator); defer list.deinit(); + + try list.append(1); + try list.append(2); + try list.append(3); + + for (list.items) |item| { + std.debug.print("{d}\n", .{item}); + } } ``` -起初这显得有些啰嗦,但你很快就会明白其价值: +这种设计的好处: + +1. **测试友好**:测试时使用 `std.testing.allocator`,会自动检测内存泄漏并报告 +2. **策略灵活**:可以根据场景选择分配器,比如用 `ArenaAllocator` 批量分配后一次性释放 +3. **零全局状态**:不依赖全局堆,代码更容易推理 -1. **可测试性**:测试时可以用 `std.testing.allocator`,它会自动检测内存泄漏 -2. **灵活性**:可以为不同场景选择不同的分配策略,比如竞技场分配器(arena allocator)用于一次性批量分配 -3. **显式性**:代码读者能立刻知道"这里有堆分配" +起初觉得到处传分配器很繁琐,但用久了反而觉得这种"明确化"非常有价值——你始终清楚地知道哪里在分配内存。 ## [comptime:编译时计算]($heading.id('comptime')) -`comptime` 是 Zig 最强大也最独特的特性。它允许在编译期运行任意 Zig 代码,实现泛型、代码生成等功能: +`comptime` 是 Zig 最具魔力的特性。它允许在编译期执行任意 Zig 代码,实现泛型、类型计算、条件编译等: + +```zig +// 泛型函数:类型是 comptime 参数 +fn max(comptime T: type, a: T, b: T) T { + return if (a > b) a else b; +} + +pub fn main() void { + std.debug.print("{d}\n", .{max(i32, 3, 7)}); + std.debug.print("{d}\n", .{max(f64, 3.14, 2.71)}); +} +``` + +更强大的用法——在编译期生成类型: ```zig -fn Vec(comptime T: type, comptime size: usize) type { +fn Queue(comptime T: type) type { return struct { - data: [size]T, + items: std.ArrayList(T), + + pub fn init(allocator: std.mem.Allocator) @This() { + return .{ .items = std.ArrayList(T).init(allocator) }; + } - pub fn init() @This() { - return .{ .data = std.mem.zeroes([size]T) }; + pub fn push(self: *@This(), item: T) !void { + try self.items.append(item); + } + + pub fn pop(self: *@This()) ?T { + if (self.items.items.len == 0) return null; + return self.items.orderedRemove(0); } }; } - -const Vec3f = Vec(f32, 3); -const Vec4i = Vec(i32, 4); ``` -类型本身就是值,可以在编译时传递、计算和返回。这避免了 C++ 模板的复杂性,也不需要 Rust 那样的 trait 系统就能实现泛型。 - -初次接触这个概念时我很困惑,但当我意识到"编译时和运行时代码用的是同一种语言"时,一切都豁然开朗了。 +这比 C++ 模板更直观,也不需要 Rust 的 trait 系统就能实现完整的泛型。Zig 里类型是一等公民,可以像值一样传递和计算。 ## [构建系统]($heading.id('build-system')) -Zig 内置了构建系统,通过 `build.zig` 文件描述构建过程,本身也是 Zig 代码: +Zig 的构建系统通过 `build.zig` 文件定义,本身就是 Zig 代码: ```zig const std = @import("std"); @@ -169,76 +228,55 @@ pub fn build(b: *std.Build) void { }); b.installArtifact(exe); + + const run = b.addRunArtifact(exe); + const run_step = b.step("run", "Run the app"); + run_step.dependOn(&run.step); } ``` -运行 `zig build` 即可编译。内置支持交叉编译,只需指定 `-Dtarget=aarch64-linux` 等参数,无需安装额外的交叉编译工具链。 +内置支持交叉编译,只需传入 `-Dtarget=` 参数。无需 Docker、无需额外工具链,一台机器就可以为所有平台构建。 -## [C 互操作]($heading.id('c-interop')) +## [与 C 的互操作]($heading.id('c-interop')) -Zig 与 C 的互操作是其核心特性之一。你可以直接导入 C 头文件: +Zig 可以直接导入 C 头文件,这是其核心特性之一: ```zig const c = @cImport({ @cInclude("stdio.h"); - @cInclude("stdlib.h"); }); pub fn main() void { - _ = c.printf("Hello from C!\n"); + _ = c.printf("Hello from C API!\n"); } ``` -Zig 也可以作为 C 编译器使用(`zig cc`),这意味着你可以用它来编译现有的 C/C++ 项目,并且利用其内置的 musl 等 libc 实现来生成静态链接的可执行文件。 - -## [让我印象深刻的地方]($heading.id('highlights')) - -经过几周的使用,有几点让我特别印象深刻: - -**1. 错误信息质量很高** - -Zig 的编译器错误信息通常很清晰,直接指出问题所在并给出建议。虽然还不及 Rust,但远好于 C/C++。 - -**2. 工具链的一体化** - -`zig` 这个二进制文件集成了编译器、构建系统、包管理器、C 编译器、格式化工具等,不需要像 C++ 项目那样折腾 CMake、Conan 等各种工具的组合。 - -**3. 调试构建自动检查** - -在调试模式下,Zig 会自动检查整数溢出、越界访问等问题,而不是静默地产生未定义行为。这在开发阶段非常有用。 - -**4. 零成本抽象** - -`comptime` 和内联函数让你可以写出高度抽象的代码,编译后与手写的低级代码性能相当。 - -## [遇到的挑战]($heading.id('challenges')) - -当然,上手过程也有不少挑战: - -**语言仍在演进**。Zig 还未到 1.0,API 变化较频繁。我在查阅一些网上的教程时,发现许多代码因为版本差异已经无法编译。建议始终参考与你所用版本对应的官方文档。 +`zig cc` 还可以直接当作 C/C++ 编译器使用,支持 musl 静态链接,可以生成真正的"单文件可执行"。 -**学习曲线**。`comptime` 的概念虽然强大,但初学时确实需要一些时间才能真正理解。与此类似,分配器系统起初感觉繁琐。 +## [初体验总结]($heading.id('summary')) -**生态系统较小**。相比 Rust 或 Go,Zig 的第三方库数量还比较少。对于很多需求,你可能需要直接使用 C 库。 +经过几周的摸索,我对 Zig 的整体印象是:**这是一门设计非常有想法的语言,哲学上的一致性令人印象深刻。** -**文档还不够完善**。标准库的文档相比其他语言来说还比较稀疏,很多时候需要直接读源码。 +**喜欢的地方:** -## [总结]($heading.id('conclusion')) +- 没有隐藏行为,代码读起来所见即所得 +- 错误处理优雅,既明确又不繁琐 +- `comptime` 系统强大而简洁,没有 C++ 模板的复杂性 +- 工具链一体化,无需折腾各种外部工具 +- 与 C 的互操作是一等公民,不是事后补丁 -Zig 是一门令人耳目一新的语言。它没有试图做所有事情,而是专注于做好一件事:提供比 C 更好的系统级编程体验,同时保持简单性和可预测性。 +**需要适应的地方:** -如果你: -- 在做系统编程或嵌入式开发 -- 想要一个现代的 C 替代品,但不需要 Rust 的复杂性 -- 对编译时元编程感兴趣 -- 需要与 C 代码深度互操作 +- 语言仍在开发中(未到 1.0),API 时常变化 +- 生态系统相对较小,很多需求要直接调 C 库 +- `comptime` 的心智模型需要时间建立 +- 文档不够完善,有时需要直接阅读标准库源码 -那么 Zig 值得认真考虑。 +**适合 Zig 的场景:** -对于我自己,我打算继续深入学习 Zig,可能会用它重写一些之前用 C 写的小工具。语言的哲学理念——显式优于隐式、没有隐藏的控制流——与我的编程价值观非常契合。 +- 系统编程、嵌入式开发 +- 需要与现有 C 代码库深度集成 +- 对可执行文件大小和启动性能敏感的场景 +- 作为 C 的现代替代品,但不想引入 Rust 的复杂性 -相关资源: -- [Zig 官网](https://ziglang.org/) -- [Zig 语言参考](https://ziglang.org/documentation/master/) -- [ziglearn.org](https://ziglearn.org/) -- [Zig 标准库源码](https://github.com/ziglang/zig/tree/master/lib/std) +总的来说,Zig 值得每一个系统程序员认真了解。它在"给程序员完整控制权"和"避免 C 的历史包袱"之间找到了一个有趣的平衡点。我打算继续深入学习,看看它是否能成为我工具箱里的常规工具。