From 4de0d4d04222d2bfe98e6bd5c02ae9138266d497 Mon Sep 17 00:00:00 2001 From: jinzhongjia Date: Tue, 2 Sep 2025 23:12:36 +0800 Subject: [PATCH 1/4] =?UTF-8?q?docs(course/update):=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=20Zig=200.15.1=20=E7=89=88=E6=9C=AC=E5=8D=87=E7=BA=A7=E4=B8=8E?= =?UTF-8?q?=E5=8F=98=E6=9B=B4=E8=AF=B4=E6=98=8E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 0.15.1 版本主要特性与破坏性变更详细解读文档 - 补充从 0.14.0 升级到 0.15.1 的迁移指南与代码适配示例 - 涵盖编译器、语言、标准库、构建系统、工具链等升级细节 - 说明 Writergate、usingnamespace 移除、ArrayList 非托管化等重点调整 - 提供常见问题解决方案与升级建议 --- course/update/0.15.1-description.md | 232 ++++++ course/update/upgrade-0.15.1.md | 1142 +++++++++++++++++++++++++++ 2 files changed, 1374 insertions(+) create mode 100644 course/update/0.15.1-description.md create mode 100644 course/update/upgrade-0.15.1.md diff --git a/course/update/0.15.1-description.md b/course/update/0.15.1-description.md new file mode 100644 index 00000000..3c9fc875 --- /dev/null +++ b/course/update/0.15.1-description.md @@ -0,0 +1,232 @@ +--- +outline: deep +comments: false +showVersion: false +--- + +# `0.15.1` + +2025/1/20,`0.15.1` 发布,历时 5 个月,有 162 位贡献者,一共进行了 647 次提交! + +Zig 官方团队直接从 `0.14.0` 跨越到了 `0.15.1`。在默认选择 Zig 的 x86 后端后,调试编译速度提高了 5 倍;正在开发的 aarch64 后端也紧随其后。同时,Writergate 事件以及一系列语言变更和标准库的调整,带来了大量的 API 破坏性更改;这预示着 async/await 的复兴;也是语言稳定化的最后防线。 + +## 编译器重大改进 + +### x86 后端性能突破 + +**调试编译速度提高了 5 倍**,这是本次更新最显著的性能改进。x86 后端现在是默认选择,为快速开发周期提供了强有力的支持。 + +### aarch64 后端开发进展 + +aarch64 后端的开发也在稳步推进,持续改进 ARM 平台支持,为多架构开发提供更好的体验。 + +### 增量编译 + +增量编译功能得到了改进,支持: +- 与文件系统监视结合使用 +- 仅检查编译错误模式 +- 更快的重建速度 + +### 多线程代码生成 + +编译器现在支持多线程代码生成,可以充分利用多核 CPU 的性能。 + +## 语言特性重大调整 + +### 移除 `usingnamespace` 关键字 + +这是一个**破坏性更改**,`usingnamespace` 关键字被完全移除。所有使用 `usingnamespace` 的代码需要重写,推荐使用显式导入替代,提高代码可读性和维护性。 + +### 移除异步关键字 + +`async` 和 `await` 关键字被移除,当前异步编程模型被移除,为未来新的异步方案做准备。这预示着 async/await 的复兴。 + +### 对非穷尽枚举的 `switch` 支持 + +新增对非穷尽枚举使用 `switch` 语句的支持,提高枚举处理的灵活性,支持未知枚举值的处理,增强代码的健壮性。 + +### 允许对布尔向量使用更多运算符 + +布尔向量现在支持更多运算符,包括逻辑运算和比较运算。 + +### 内联汇编:类型化的破坏描述符 + +内联汇编现在支持类型化的 clobber 列表,提供更好的类型安全。 + +### 指针转换增强 + +`@ptrCast` 现在允许从单项指针到切片的转换,提供更大的灵活性。 + +### undefined 运算新规则 + +对 `undefined` 值的算术运算规则发生了变化,任何与 `undefined` 的运算都返回 `undefined`。 + +### 有损转换检测 + +现在对于可能导致精度损失的整数到浮点数转换会发出编译错误。 + +## 标准库重大变更 + +### Writergate:I/O 接口完全重构 + +这是本次更新中**最重大的破坏性更改**,被社区称为 "Writergate": + +- `std.io.Reader` 和 `std.io.Writer` 接口被完全重新设计 +- 新接口采用非泛型设计 +- 缓冲区位于接口之上 +- 旨在提高性能并减少不必要的拷贝 +- **需要大量代码重写** + +### 格式化系统调整 + +格式化系统进行了重要调整: +- 调用自定义 `format` 方法需要使用 `{f}` 格式说明符 +- `format` 方法签名简化,移除了格式字符串和选项参数 +- 格式化打印不再处理 Unicode +- 新增了更多格式化说明符 + +### `ArrayList` 非托管化 + +容器类型的重要变更: +- `std.ArrayList` 现在默认采用非托管方式 +- 开发者需要显式提供分配器 +- 与其他非托管容器保持一致 +- 提供更好的内存管理控制 + +### 去泛型化链表 + +链表类型进行了重构,去除了泛型化设计。 + +### HTTP 客户端和服务器 + +标准库新增了 HTTP 支持,提供内置的 HTTP 客户端和服务器功能。 + +### TLS 客户端 + +新增内置 TLS 支持,可以建立安全的 TLS 连接。 + +### 环形缓冲区 + +新增了环形缓冲区类型,提供高效的循环缓冲区实现。 + +### 移除 BoundedArray + +`BoundedArray` 被移除,建议使用 `ArrayList` 或固定大小数组替代。 + +## 构建系统改进 + +### 移除隐式根模块 + +构建系统移除了对隐式根模块的支持,需要在构建脚本中明确指定模块,提高构建配置的明确性。 + +### macOS 文件系统监视 + +在 macOS 上新增了文件系统监视功能: +- 能够在文件更改时自动触发重建 +- 支持 `--watch` 和 `--debounce` 选项 +- 显著提高开发效率 + +### Web 界面和时间报告 + +构建系统现在支持 Web 界面和详细的时间报告功能。 + +## 模糊测试器 + +Zig 0.15.1 集成了一个内置的模糊测试器: +- 支持进程内模糊测试 +- 提供 Web UI 界面 +- 支持实时代码覆盖率显示 +- 可以快速发现代码中的问题 + +## 工具链更新 + +### LLVM 20 + +升级到 LLVM 20,带来了: +- 更好的优化支持 +- 新的目标架构支持 +- 改进的调试信息生成 +- 更好的 C++ 交互性 + +### FreeBSD 和 NetBSD libc 支持 + +在交叉编译时新增了对动态链接的 FreeBSD 和 NetBSD libc 的支持。 + +### glibc 2.42 + +升级到 glibc 2.42,并支持静态链接本机 glibc。 + +### MinGW-w64 更新 + +MinGW-w64 工具链得到了更新,改进了 Windows 交叉编译支持。 + +### zig libc 和 zig cc 增强 + +`zig libc` 和 `zig cc` 命令得到了功能增强: +- 更好的 GCC 兼容性 +- 支持更多编译选项 +- 更好的错误报告 + +## 版本跳跃说明 + +Zig 官方团队选择直接从 `0.14.0` 跳跃到 `0.15.1`,这反映了: +- 本次更新包含的重大变更数量 +- 对编译器性能的重要改进 +- 标准库接口的重大重构 +- 为未来版本奠定更好的基础 + +## 升级挑战与机遇 + +### 主要挑战 + +1. **Writergate**:I/O 接口的完全重构需要重写大量相关代码 +2. **移除 `usingnamespace`**:需要调整导入方式 +3. **异步代码调整**:需要移除 async/await 使用 +4. **ArrayList 变更**:需要调整容器使用方式 + +### 主要机遇 + +1. **编译速度提升**:5 倍的调试编译速度改进 +2. **更清晰的代码**:移除隐式行为,提高代码可读性 +3. **更好的性能**:新的 I/O 接口设计更高效 +4. **开发效率**:文件系统监视功能和模糊测试器 + +## 社区影响 + +这次更新对 Zig 社区产生了重要影响: +- **学习曲线**:新用户需要适应新的接口设计 +- **迁移工作**:现有项目需要进行大量调整 +- **性能收益**:编译速度的显著提升改善开发体验 +- **生态系统**:库作者需要更新以适配新接口 + +## 技术债务清理 + +本次更新体现了 Zig 团队对技术债务的积极清理: +- 移除了有争议的 `usingnamespace` 特性 +- 重构了性能不佳的 I/O 接口 +- 统一了容器类型的设计理念 +- 为未来的语言演进奠定基础 + +## 未来展望 + +`0.15.1` 为 Zig 的未来发展奠定了重要基础: +- **编译性能**:为大型项目开发提供更好支持 +- **接口设计**:更一致、更高效的标准库 +- **开发体验**:更快的编译和更好的工具支持 +- **语言稳定性**:移除不稳定特性,为 1.0 做准备 + +## 路线图 + +### I/O 作为接口 + +I/O 系统将继续作为接口进行发展和完善,为未来的异步编程模型做准备。 + +## 建议 + +对于 Zig 开发者: +1. **谨慎升级**:在测试环境中充分验证 +2. **分步迁移**:逐步调整代码以适配新接口 +3. **利用性能**:充分利用编译速度的改进 +4. **关注社区**:参与社区讨论,分享迁移经验 + +`0.15.1` 是 Zig 发展历程中的一个重要里程碑,虽然带来了较多的破坏性更改,但为语言的长期发展和性能提升奠定了坚实的基础。这是语言稳定化的最后防线,为 1.0 版本的发布做好了准备。 \ No newline at end of file diff --git a/course/update/upgrade-0.15.1.md b/course/update/upgrade-0.15.1.md new file mode 100644 index 00000000..11ed0714 --- /dev/null +++ b/course/update/upgrade-0.15.1.md @@ -0,0 +1,1142 @@ +--- +outline: deep +showVersion: false +--- + +本篇文档将介绍如何从 `0.14.0` 版本升级到 `0.15.1`。 + +> 本次发布包含了 162 位贡献者在 5 个月内完成的 647 次提交。在默认选择 Zig 的 x86 后端后,调试编译速度提高了 5 倍;正在开发的 aarch64 后端也紧随其后。同时,Writergate 事件以及一系列语言变更和标准库的调整,带来了大量的 API 破坏性更改。 + +## 语言变更 + +### 移除 `usingnamespace` + +`usingnamespace` 关键字已被移除。以下是一些常见用例的替代方案: + +#### 用例:条件包含 + +```zig +// 旧代码 +const builtin = @import("builtin"); +const os_impl = switch (builtin.os.tag) { + .linux => @import("os/linux.zig"), + .windows => @import("os/windows.zig"), + else => @compileError("Unsupported OS"), +}; +usingnamespace os_impl; +``` + +⬇️ + +```zig +// 新代码 +const builtin = @import("builtin"); +const os_impl = switch (builtin.os.tag) { + .linux => @import("os/linux.zig"), + .windows => @import("os/windows.zig"), + else => @compileError("Unsupported OS"), +}; + +// 显式导出所需函数 +pub const open = os_impl.open; +pub const close = os_impl.close; +pub const read = os_impl.read; +pub const write = os_impl.write; +``` + +#### 用例:实现切换 + +```zig +// 旧代码 +const MyStruct = struct { + data: u32, + + usingnamespace if (builtin.mode == .Debug) + @import("debug_impl.zig") + else + @import("release_impl.zig"); +}; +``` + +⬇️ + +```zig +// 新代码 +const Impl = if (builtin.mode == .Debug) + @import("debug_impl.zig") +else + @import("release_impl.zig"); + +const MyStruct = struct { + data: u32, + + pub fn doSomething(self: *MyStruct) void { + return Impl.doSomething(self); + } + + // 显式实现所有需要的方法 +}; +``` + +#### 用例:混入 + +```zig +// 旧代码 +fn LoggingMixin(comptime T: type) type { + return struct { + pub fn log(self: *T, message: []const u8) void { + std.log.info("{s}: {s}", .{ @typeName(T), message }); + } + }; +} + +const MyStruct = struct { + data: u32, + usingnamespace LoggingMixin(@This()); +}; +``` + +⬇️ + +```zig +// 新代码 +fn LoggingMixin(comptime T: type) type { + return struct { + pub fn log(self: *T, message: []const u8) void { + std.log.info("{s}: {s}", .{ @typeName(T), message }); + } + }; +} + +const MyStruct = struct { + data: u32, + + const Mixin = LoggingMixin(@This()); + + pub fn log(self: *MyStruct, message: []const u8) void { + Mixin.log(self, message); + } +}; +``` + +### 移除 `async` 和 `await` 关键字 + +`async` 和 `await` 关键字已被移除。这为未来引入新的异步编程方案做准备。 + +```zig +// 旧代码 - 将不再工作 +fn asyncFunction() async void { + // 异步代码 +} + +fn caller() void { + const frame = async asyncFunction(); + await frame; +} +``` + +目前需要使用其他方式处理并发,等待未来版本中新的异步编程支持。 + +### 对非穷尽枚举的 `switch` 支持 + +现在可以对非穷尽枚举使用 `switch` 语句: + +```zig +const MyEnum = enum(u8) { + foo = 1, + bar = 2, + _, +}; + +fn handleEnum(value: MyEnum) void { + switch (value) { + .foo => std.debug.print("foo\n", .{}), + .bar => std.debug.print("bar\n", .{}), + else => std.debug.print("unknown\n", .{}), + } +} +``` + +### 允许对布尔向量使用更多运算符 + +布尔向量现在支持更多运算符: + +```zig +test "boolean vector operations" { + const vec_a: @Vector(4, bool) = .{ true, false, true, false }; + const vec_b: @Vector(4, bool) = .{ false, true, true, false }; + + const and_result = vec_a & vec_b; + const or_result = vec_a | vec_b; + const xor_result = vec_a ^ vec_b; + const not_result = ~vec_a; +} +``` + +### 内联汇编:类型化的破坏描述符 + +内联汇编现在支持类型化的 clobber 列表: + +```zig +// 旧代码 +asm volatile ("mov %[src], %[dst]" + : [dst] "=r" (dst) + : [src] "r" (src) + : "memory" // 字符串形式 +); +``` + +⬇️ + +```zig +// 新代码 +asm volatile ("mov %[src], %[dst]" + : [dst] "=r" (dst) + : [src] "r" (src) + : .memory // 类型化形式 +); +``` + +### 允许 `@ptrCast` 从单项指针到切片的转换 + +现在可以使用 `@ptrCast` 将单项指针转换为切片: + +```zig +test "ptrCast to slice" { + var value: u32 = 42; + const ptr: *u32 = &value; + + // 新功能:将单项指针转换为切片 + const slice: []u32 = @ptrCast(ptr); + + std.testing.expect(slice[0] == 42); +} +``` + +### 对 `undefined` 进行算术运算的新规则 + +`undefined` 值的算术运算规则发生了变化: + +```zig +test "undefined arithmetic" { + const a: i32 = undefined; + const b: i32 = 10; + + // 任何与 undefined 的运算都返回 undefined + const result = a + b; // result 是 undefined + _ = result; + + // 更安全的做法 + const safe_a: i32 = 0; // 显式初始化 + const safe_result = safe_a + b; + std.testing.expect(safe_result == 10); +} +``` + +### 对从整数到浮点数的有损转换发出错误 + +现在对于可能导致精度损失的转换会发出编译错误: + +```zig +test "lossy integer to float conversion" { + const large_int: u64 = 0x1FFFFFFFFFFFFF; // 53 位 + + // 这将产生编译错误,因为 f64 只有 52 位尾数 + // const float_val: f64 = @floatFromInt(large_int); // 错误! + + // 需要显式使用有损转换 + const float_val: f64 = @floatFromInt(@as(u53, @truncate(large_int))); + + std.debug.print("Float: {}\n", .{float_val}); +} +``` + +## 标准库 + +### Writergate + +这是本次更新中最重大的破坏性更改,原有的 `std.io` 中的读写器接口被完全重新设计。 + +#### 动机 + +旧的 I/O 系统存在以下问题: +- 泛型接口导致编译时间过长 +- 缓冲区管理不一致 +- 性能不佳,存在不必要的内存拷贝 +- 接口复杂,难以优化 + +#### 适配器 API + +新的设计引入了适配器模式: + +```zig +// 旧的泛型接口 +fn processData(reader: anytype, writer: anytype) !void { + var buffer: [1024]u8 = undefined; + while (true) { + const bytes_read = try reader.read(&buffer); + if (bytes_read == 0) break; + try writer.writeAll(buffer[0..bytes_read]); + } +} +``` + +⬇️ + +```zig +// 新的适配器接口 +fn processData(reader: std.Io.Reader, writer: std.Io.Writer) !void { + var buffer: [1024]u8 = undefined; + while (true) { + const bytes_read = try reader.read(&buffer); + if (bytes_read == 0) break; + try writer.writeAll(buffer[0..bytes_read]); + } +} + +// 使用时需要适配器 +const file = try std.fs.cwd().openFile("input.txt", .{}); +defer file.close(); + +const stdout = std.io.getStdOut(); + +try processData( + file.reader().adapter(), // 适配器转换 + stdout.writer().adapter(), // 适配器转换 +); +``` + +#### 新的 `std.Io.Writer` 和 `std.Io.Reader` API + +新的 API 采用非泛型设计: + +```zig +// std.Io.Writer 的定义 +pub const Writer = struct { + ptr: *anyopaque, + vtable: *const VTable, + + pub const VTable = struct { + write: *const fn (*anyopaque, []const u8) anyerror!usize, + writeAll: *const fn (*anyopaque, []const u8) anyerror!void, + writeByte: *const fn (*anyopaque, u8) anyerror!void, + }; + + pub fn write(self: Writer, bytes: []const u8) !usize { + return self.vtable.write(self.ptr, bytes); + } + + pub fn writeAll(self: Writer, bytes: []const u8) !void { + return self.vtable.writeAll(self.ptr, bytes); + } +}; +``` + +#### `std.fs.File.Reader` 和 `std.fs.File.Writer` + +文件 I/O 的使用方式也发生了变化: + +```zig +// 旧代码 +const file = try std.fs.cwd().openFile("data.txt", .{}); +defer file.close(); + +const reader = file.reader(); +var buffer: [1024]u8 = undefined; +const bytes_read = try reader.read(&buffer); +``` + +⬇️ + +```zig +// 新代码 +const file = try std.fs.cwd().openFile("data.txt", .{}); +defer file.close(); + +// 方式 1:直接使用文件方法 +var buffer: [1024]u8 = undefined; +const bytes_read = try file.read(&buffer); + +// 方式 2:使用新的 Reader 接口 +const reader = file.reader(); +const io_reader = reader.adapter(); +const bytes_read2 = try io_reader.read(&buffer); +``` + +#### 升级 `std.io.getStdOut().writer().print()` + +标准输出的使用方式也需要调整: + +```zig +// 旧代码 +const stdout = std.io.getStdOut().writer(); +try stdout.print("Hello, {s}!\n", .{"World"}); +``` + +⬇️ + +```zig +// 新代码 +// 方式 1:使用 std.debug.print(推荐) +std.debug.print("Hello, {s}!\n", .{"World"}); + +// 方式 2:使用新的 Writer 接口 +const stdout = std.io.getStdOut(); +const writer = stdout.writer().adapter(); +try writer.print("Hello, {s}!\n", .{"World"}); + +// 方式 3:直接使用文件方法 +const stdout = std.io.getStdOut(); +try stdout.writeAll("Hello, World!\n"); +``` + +#### 重构 `std.compress.flate` + +压缩相关的代码也需要大量修改: + +```zig +// 旧代码 +var deflate_stream = std.compress.flate.deflateStream(allocator, writer); +defer deflate_stream.deinit(); +try deflate_stream.writer().writeAll(data); +try deflate_stream.finish(); +``` + +⬇️ + +```zig +// 新代码 +var deflate_stream = std.compress.flate.DeflateStream.init(allocator, writer.adapter()); +defer deflate_stream.deinit(); +try deflate_stream.writeAll(data); +try deflate_stream.finish(); +``` + +#### 删除 `CountingWriter` + +`CountingWriter` 被删除,需要手动计数: + +```zig +// 旧代码 +var counting_writer = std.io.countingWriter(base_writer); +``` + +⬇️ + +```zig +// 新代码 - 需要手动计数 +var bytes_written: usize = 0; +``` + +#### 删除 `BufferedWriter` + +`BufferedWriter` 被重构: + +```zig +// 旧代码 +var buffered_writer = std.io.bufferedWriter(base_writer); +``` + +⬇️ + +```zig +// 新代码 +var buffer: [4096]u8 = undefined; +var buffered_writer = std.io.BufferedWriter(4096, @TypeOf(base_writer)).init(base_writer); +``` + +### 调用 `format` 方法需要使用 `{f}` + +现在调用自定义的 `format` 方法需要使用 `{f}` 格式说明符: + +```zig +const Point = struct { + x: f32, + y: f32, + + pub fn format(self: Point, writer: anytype) !void { + try writer.print("Point({d}, {d})", .{ self.x, self.y }); + } +}; + +// 使用时必须使用 {f} +const point = Point{ .x = 1.0, .y = 2.0 }; +std.debug.print("{f}\n", .{point}); // 注意使用 {f} +``` + +### `format` 方法不再使用格式字符串或选项 + +格式化方法的签名已经简化: + +```zig +// 旧代码 +const Point = struct { + x: f32, + y: f32, + + pub fn format( + self: Point, + comptime fmt: []const u8, // 被移除 + options: std.fmt.FormatOptions, // 被移除 + writer: anytype, + ) !void { + _ = fmt; + _ = options; + try writer.print("Point({d}, {d})", .{ self.x, self.y }); + } +}; +``` + +⬇️ + +```zig +// 新代码 +const Point = struct { + x: f32, + y: f32, + + pub fn format( + self: Point, + writer: anytype, // 只保留 writer 参数 + ) !void { + try writer.print("Point({d}, {d})", .{ self.x, self.y }); + } +}; +``` + +### 格式化打印不再处理 Unicode + +Unicode 处理被移除,需要手动处理: + +```zig +// 旧代码 +std.debug.print("你好,{s}!\n", .{"世界"}); // 自动处理 Unicode +``` + +⬇️ + +```zig +// 新代码 - 需要手动处理 Unicode +const message = "你好,世界!"; +std.debug.print("{s}\n", .{message}); // 仍然可以显示,但不保证所有 Unicode 处理 +``` + +### 新的格式化打印说明符 + +新增了一些格式化说明符: + +```zig +const value: u32 = 255; + +// 新的格式化选项 +std.debug.print("{d}\n", .{value}); // 十进制:255 +std.debug.print("{x}\n", .{value}); // 十六进制:ff +std.debug.print("{X}\n", .{value}); // 大写十六进制:FF +std.debug.print("{o}\n", .{value}); // 八进制:377 +std.debug.print("{b}\n", .{value}); // 二进制:11111111 + +// 浮点数格式化 +const pi: f64 = 3.14159; +std.debug.print("{d:.2}\n", .{pi}); // 保留两位小数:3.14 +std.debug.print("{e}\n", .{pi}); // 科学计数法:3.14159e+00 + +// 指针和切片 +const ptr: *u32 = &value; +const slice: []const u8 = "hello"; +std.debug.print("{*}\n", .{ptr}); // 指针地址 +std.debug.print("{s}\n", .{slice}); // 字符串 +std.debug.print("{any}\n", .{slice}); // 通用格式化 +``` + +### 去泛型化链表 + +链表类型也进行了重构: + +```zig +// 旧代码 +const Node = std.SinglyLinkedList(i32).Node; +var list = std.SinglyLinkedList(i32){}; +var node = Node{ .data = 42 }; +list.prepend(&node); +``` + +⬇️ + +```zig +// 新代码 +const SinglyLinkedList = std.SinglyLinkedList; +const Node = SinglyLinkedList.Node; + +var list: SinglyLinkedList = .{}; +var node = Node{ .data = @as(*anyopaque, @ptrCast(&@as(i32, 42))) }; +list.prepend(&node); + +// 或者使用新的 API +var typed_list = std.DoublyLinkedList(i32){}; +var typed_node = std.DoublyLinkedList(i32).Node{ .data = 42 }; +typed_list.append(&typed_node); +``` + +### `std.Progress` 支持进度条转义码 + +进度条系统得到了增强,支持更多的终端转义码。 + +### HTTP 客户端和服务器 + +标准库新增了 HTTP 支持: + +```zig +// HTTP 客户端示例 +const std = @import("std"); + +pub fn main() !void { + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + defer _ = gpa.deinit(); + const allocator = gpa.allocator(); + + var client = std.http.Client{ .allocator = allocator }; + defer client.deinit(); + + const uri = std.Uri.parse("https://httpbin.org/get") catch unreachable; + + var headers = std.http.Headers{ .allocator = allocator }; + defer headers.deinit(); + + try headers.append("User-Agent", "Zig HTTP Client"); + + var request = try client.open(.GET, uri, headers, .{}); + defer request.deinit(); + + try request.send(.{}); + try request.wait(); + + const body = try request.reader().readAllAlloc(allocator, 8192); + defer allocator.free(body); + + std.debug.print("Response: {s}\n", .{body}); +} +``` + +### TLS 客户端 + +内置 TLS 支持: + +```zig +// TLS 连接示例 +const std = @import("std"); + +pub fn main() !void { + var gpa = std.heap.GeneralPurposeAllocator(.{}){}; + defer _ = gpa.deinit(); + const allocator = gpa.allocator(); + + const address = try std.net.Address.parseIp("93.184.216.34", 443); // example.com + const stream = try std.net.tcpConnectToAddress(address); + defer stream.close(); + + var tls_client = try std.crypto.tls.Client.init(stream, .{ + .host = "example.com", + .allocator = allocator, + }); + defer tls_client.deinit(); + + const request = "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"; + try tls_client.writeAll(request); + + var buffer: [4096]u8 = undefined; + const bytes_read = try tls_client.read(&buffer); + std.debug.print("Response: {s}\n", .{buffer[0..bytes_read]}); +} +``` + +### `ArrayList`:将非托管模式设为默认 + +这是一个重大的破坏性更改。`std.ArrayList` 现在默认采用非托管 (unmanaged) 方式: + +```zig +// 旧代码 +const std = @import("std"); + +fn oldArrayListExample(allocator: std.mem.Allocator) !void { + var list = std.ArrayList(i32).init(allocator); + defer list.deinit(); + + try list.append(42); + try list.appendSlice(&[_]i32{ 1, 2, 3 }); + + for (list.items) |item| { + std.debug.print("{d} ", .{item}); + } +} +``` + +⬇️ + +```zig +// 新代码 +const std = @import("std"); + +fn newArrayListExample(allocator: std.mem.Allocator) !void { + // 方式 1:使用新的 ArrayListUnmanaged + var list: std.ArrayListUnmanaged(i32) = .empty; + defer list.deinit(allocator); + + try list.append(allocator, 42); + try list.appendSlice(allocator, &[_]i32{ 1, 2, 3 }); + + for (list.items) |item| { + std.debug.print("{d} ", .{item}); + } +} + +// 方式 2:使用别名保持兼容性 +fn compatibilityExample(allocator: std.mem.Allocator) !void { + // ArrayList 现在是 ArrayListUnmanaged 的别名 + const ArrayList = std.ArrayListUnmanaged; + var list: ArrayList(i32) = .empty; + defer list.deinit(allocator); + + try list.append(allocator, 42); +} + +// 方式 3:使用新的初始化方法 +fn newInitExample(allocator: std.mem.Allocator) !void { + var list = std.ArrayList(i32).init(allocator); // 仍然可用,但已弃用 + defer list.deinit(); + + // 或者使用新的方式 + var new_list: std.ArrayList(i32) = .{}; + defer new_list.deinit(allocator); + + try new_list.append(allocator, 42); +} +``` + +其他容器类型也发生了类似的变化: + +```zig +// HashMap +var map: std.HashMapUnmanaged([]const u8, i32, std.hash_map.StringContext, 80) = .{}; +defer map.deinit(allocator); + +try map.put(allocator, "key", 42); +const value = map.get("key"); + +// ArrayHashMap +var array_map: std.ArrayHashMapUnmanaged([]const u8, i32, std.hash_map.StringContext, false) = .{}; +defer array_map.deinit(allocator); + +try array_map.put(allocator, "key", 42); + +// PriorityQueue +var pq: std.PriorityQueueUnmanaged(i32, void, compareInts) = .{}; +defer pq.deinit(allocator); + +try pq.add(allocator, 42); + +fn compareInts(context: void, a: i32, b: i32) std.math.Order { + _ = context; + return std.math.order(a, b); +} +``` + +### 环形缓冲区 + +新增了环形缓冲区类型: + +```zig +const RingBuffer = std.RingBuffer; + +// 创建环形缓冲区 +var buffer: [16]u8 = undefined; +var ring = RingBuffer.init(&buffer); + +// 写入数据 +const data = "Hello, World!"; +const written = ring.write(data); +std.debug.print("Written {} bytes\n", .{written}); + +// 读取数据 +var read_buffer: [32]u8 = undefined; +const read_count = ring.read(&read_buffer); +std.debug.print("Read: {s}\n", .{read_buffer[0..read_count]}); +``` + +### 移除 `BoundedArray` + +`BoundedArray` 被移除,建议使用其他替代方案: + +```zig +// 旧代码 +var bounded = std.BoundedArray(i32, 10).init(0); +try bounded.append(42); +``` + +⬇️ + +```zig +// 新代码 - 使用 ArrayList 或数组 +var list: std.ArrayListUnmanaged(i32) = .empty; +defer list.deinit(allocator); + +// 或者使用固定大小数组 +var array: [10]i32 = undefined; +var count: usize = 0; + +if (count < array.len) { + array[count] = 42; + count += 1; +} +``` + +### 删除和弃用 + +本次更新中删除和弃用了多个 API,需要使用新的替代方案。 + +## 构建系统 + +### 移除已弃用的隐式根模块 + +构建系统中已移除对隐式根模块的支持,需要在构建脚本中明确指定模块: + +```zig +// 旧的 build.zig +pub fn build(b: *std.Build) void { + const exe = b.addExecutable(.{ + .name = "app", + .root_source_file = b.path("src/main.zig"), + .target = target, + .optimize = optimize, + }); +} +``` + +⬇️ + +```zig +// 新的 build.zig +pub fn build(b: *std.Build) void { + const exe = b.addExecutable(.{ + .name = "app", + .root_module = b.createModule(.{ + .root_source_file = b.path("src/main.zig"), + .target = target, + .optimize = optimize, + }), + }); +} +``` + +### macOS 文件系统监视 + +在 macOS 上,构建系统现在支持文件系统监视功能,能够在文件更改时自动触发重建: + +```bash +# 启用文件系统监视 +zig build --watch + +# 设置去抖动时间(默认50ms) +zig build --watch --debounce 100 +``` + +### Web 界面和时间报告 + +构建系统现在支持 Web 界面和详细的时间报告功能。 + +## 编译器 + +### x86 后端 + +在默认选择 Zig 的 x86 后端的情况下,调试编译速度提高了 5 倍。这是本次更新最显著的性能改进: + +```bash +# 使用新的 x86 后端(默认) +zig build -Doptimize=Debug + +# 如果需要使用 LLVM 后端 +zig build -Doptimize=Debug -fLLVM +``` + +### aarch64 后端 + +aarch64 后端的开发也在稳步推进,为 ARM 平台提供更好的支持。 + +### 增量编译 + +增量编译功能得到了改进: + +```bash +# 启用增量编译 +zig build -fincremental + +# 结合文件系统监视 +zig build -fincremental --watch + +# 仅检查编译错误(不生成二进制文件) +zig build -fincremental -fno-emit-bin --watch +``` + +### 多线程代码生成 + +编译器现在支持多线程代码生成: + +```bash +# 控制编译线程数 +zig build -j4 # 使用 4 个线程 +zig build -j # 使用所有可用 CPU 核心 + +# 禁用多线程编译 +zig build -j1 +``` + +### 允许在模块级别配置 UBSan 模式 + +现在可以在模块级别配置 UBSan(未定义行为检测器): + +```zig +// build.zig 中的配置 +const exe = b.addExecutable(.{ + .name = "app", + .root_module = b.createModule(.{ + .root_source_file = b.path("src/main.zig"), + .target = target, + .optimize = optimize, + .sanitize_c = true, // 启用 C 代码的 UBSan + }), +}); + +// 或者使用命令行 +zig build -Dsanitize-c +``` + +### 将测试编译为目标文件 + +现在可以将测试编译为目标文件而不是可执行文件: + +```bash +# 将测试编译为 .o 文件 +zig test src/main.zig --object + +# 将测试编译为静态库 +zig test src/main.zig --library + +# 将测试编译为动态库 +zig test src/main.zig --dynamic-library +``` + +### Zig 初始化 + +`zig init` 命令得到了改进: + +```bash +# 创建新项目 +zig init + +# 创建库项目 +zig init --lib + +# 创建可执行项目 +zig init --exe + +# 指定项目名称 +zig init --name my-project + +# 在现有目录中初始化 +zig init . +``` + +## 链接器 + +链接器得到了多项改进和优化。 + +## 模糊测试器 + +Zig 0.15.1 集成了一个内置的模糊测试器: + +```bash +# 启动模糊测试 +zig build test --fuzz + +# 指定端口 +zig build test --fuzz --port 8080 + +# 指定测试时间 +zig build test --fuzz --timeout 60 +``` + +```zig +// 模糊测试例子 +test "fuzz string parsing" { + const input_bytes = std.testing.fuzzInput(.{}); + + // 测试字符串解析函数 + const result = parseString(input_bytes); + + // 确保不会崩溃 + _ = result catch |err| { + // 预期的错误可以忽略 + if (err == error.InvalidInput) return; + return err; + }; +} + +fn parseString(input: []const u8) ![]const u8 { + if (input.len == 0) return error.InvalidInput; + // 解析逻辑... + return input; +} +``` + +## 错误修复 + +本次发布修复了大量错误。 + +### 本次发布包含的错误 + +Zig 目前仍存在一些已知的 bugs,包括一些编译错误。 + +## 工具链 + +### LLVM 20 + +本次更新升级到 LLVM 20,带来了以下改进: +- 更好的优化支持 +- 新的目标架构支持 +- 改进的调试信息生成 +- 更好的 C++ 交互性 + +### 在交叉编译时支持动态链接的 FreeBSD libc + +```bash +# 交叉编译到 FreeBSD +zig build -Dtarget=x86_64-freebsd-gnu +zig build -Dtarget=aarch64-freebsd-gnu + +# 使用动态链接的 libc +zig build -Dtarget=x86_64-freebsd-gnu -Ddynamic-linker +``` + +### 在交叉编译时支持动态链接的 NetBSD libc + +```bash +# 交叉编译到 NetBSD +zig build -Dtarget=x86_64-netbsd-gnu +zig build -Dtarget=aarch64-netbsd-gnu + +# 使用 NetBSD 系统 libc +zig cc -target x86_64-netbsd-gnu program.c +``` + +### glibc 2.42 + +升级到 glibc 2.42,并支持静态链接本地 glibc: + +```bash +# 使用系统 glibc 静态链接 +zig build -Dtarget=native-linux-gnu -Dlinkage=static + +# 指定 glibc 版本 +zig build -Dtarget=x86_64-linux-gnu.2.42 +``` + +#### 允许静态链接本机 glibc + +现在可以静态链接本机系统的 glibc。 + +### MinGW-w64 + +MinGW-w64 工具链得到了更新: + +```bash +# Windows 交叉编译 +zig build -Dtarget=x86_64-windows-gnu +zig build -Dtarget=aarch64-windows-gnu + +# 使用 MinGW-w64 工具链 +zig cc -target x86_64-windows-gnu program.c +``` + +### zig libc + +`zig libc` 命令得到了增强: + +```bash +# 查看当前目标的 libc 配置 +zig libc + +# 查看指定目标的 libc +zig libc -target x86_64-linux-gnu + +# 查看所有可用的 libc +zig targets | grep libc +``` + +### zig cc + +`zig cc` 作为 C 编译器的功能得到了增强: + +```bash +# 更好的 GCC 兼容性 +zig cc -std=c11 -O2 program.c + +# 支持更多编译选项 +zig cc -march=native -mtune=native program.c + +# 更好的错误报告 +zig cc -Wall -Wextra program.c +``` + +### zig objcopy 回归 + +`zig objcopy` 命令存在一些回归问题,正在修复中。 + +## 路线图 + +### I/O 作为接口 + +I/O 系统将继续作为接口进行发展和完善。 + +## 升级建议 + +由于此次更新包含多项破坏性更改,建议开发者在升级至 0.15.1 版本时: + +### 升级步骤 + +1. **备份现有代码**:在开始升级之前做好备份 + +2. **分步骤进行**: + - 首先处理 `usingnamespace` 的移除 + - 然后处理 I/O 系统的重构 + - 最后处理 ArrayList 等容器的变更 + +3. **使用编译器检查**: + ```bash + # 检查编译错误 + zig build-exe src/main.zig + + # 使用新的 x86 后端加速编译 + zig build -fno-LLVM + ``` + +4. **测试全面性**:确保所有功能在新版本下正常运行 + +5. **利用新特性**: + - 使用新的 x86 后端提高编译速度 + - 使用文件系统监视功能 + - 尝试增量编译 + +### 常见问题和解决方案 + +1. **I/O 代码编译错误**:参考上面的 Writergate 部分 +2. **`usingnamespace` 错误**:使用显式导入替代 +3. **ArrayList 错误**:改为使用 ArrayListUnmanaged +4. **格式化错误**:更新 format 方法签名 + +## 注意事项 + +- 这次升级的破坏性更改较多,建议在测试环境中进行充分测试 +- I/O 接口的重构可能需要较多的代码调整工作 +- 新的性能改进主要体现在编译速度上 +- 文件系统监视功能有助于提高开发效率 + +完整的发布说明可在 [Zig 官方网站](https://ziglang.org/download/0.15.1/release-notes.html) 查看。 \ No newline at end of file From 334646968756e8fcf30257ac0cbf5a3bd5e92b25 Mon Sep 17 00:00:00 2001 From: xihale Date: Fri, 5 Sep 2025 19:48:55 +0800 Subject: [PATCH 2/4] Improve wording and formatting in release notes --- course/update/0.15.1-description.md | 78 +++++++++-------- course/update/upgrade-0.15.1.md | 125 ++++++++++++++-------------- 2 files changed, 108 insertions(+), 95 deletions(-) diff --git a/course/update/0.15.1-description.md b/course/update/0.15.1-description.md index 3c9fc875..8f9a3835 100644 --- a/course/update/0.15.1-description.md +++ b/course/update/0.15.1-description.md @@ -6,64 +6,65 @@ showVersion: false # `0.15.1` -2025/1/20,`0.15.1` 发布,历时 5 个月,有 162 位贡献者,一共进行了 647 次提交! +2025/1/20,`0.15.1` 发布,自上一个版本来历时 5 个月,共有 162 位贡献者参与,进行了 647 次提交! -Zig 官方团队直接从 `0.14.0` 跨越到了 `0.15.1`。在默认选择 Zig 的 x86 后端后,调试编译速度提高了 5 倍;正在开发的 aarch64 后端也紧随其后。同时,Writergate 事件以及一系列语言变更和标准库的调整,带来了大量的 API 破坏性更改;这预示着 async/await 的复兴;也是语言稳定化的最后防线。 +Zig 官方团队直接从 `0.14.0` 跨越到了 `0.15.1`。在默认选择 Zig 的 x86 后端后,调试编译速度提高了 **5** 倍;正在开发的 aarch64 后端也紧随其后。同时,随着 `Writergate` 事件以及一系列语言变更和标准库的调整,**大量** API 有破坏性更改;这预示着 async/await 即将重生;也是语言稳定化的最后关头。 ## 编译器重大改进 ### x86 后端性能突破 -**调试编译速度提高了 5 倍**,这是本次更新最显著的性能改进。x86 后端现在是默认选择,为快速开发周期提供了强有力的支持。 +**调试模式**的编译速度提高了 **5** 倍;这是本次更新最显著的性能改进。x86 后端现在是**调试模式**的默认选择,为缩短开发周期提供了强有力的支持。 ### aarch64 后端开发进展 -aarch64 后端的开发也在稳步推进,持续改进 ARM 平台支持,为多架构开发提供更好的体验。 +aarch64 后端的开发也在稳步推进,持续优化 ARM 平台支持,为多架构开发提供更好的体验。 -### 增量编译 +### 增量编译功能增强 + +增量编译功能得到了进一步优化,现在支持: -增量编译功能得到了改进,支持: - 与文件系统监视结合使用 - 仅检查编译错误模式 - 更快的重建速度 ### 多线程代码生成 -编译器现在支持多线程代码生成,可以充分利用多核 CPU 的性能。 +编译器现已支持多线程代码生成,能够充分利用多核 CPU 的性能优势。 ## 语言特性重大调整 ### 移除 `usingnamespace` 关键字 -这是一个**破坏性更改**,`usingnamespace` 关键字被完全移除。所有使用 `usingnamespace` 的代码需要重写,推荐使用显式导入替代,提高代码可读性和维护性。 +这是一个**破坏性变更**,`usingnamespace` 关键字被完全移除。所有使用 `usingnamespace` 的代码都需要重写,建议采用显式导入方式替代,以提高代码可读性和可维护性。 ### 移除异步关键字 -`async` 和 `await` 关键字被移除,当前异步编程模型被移除,为未来新的异步方案做准备。这预示着 async/await 的复兴。 +`async` 和 `await` 关键字已被移除,当前异步编程模型也随之取消,为未来新的异步方案做准备。这预示着 Zig 协程 的重生。 -### 对非穷尽枚举的 `switch` 支持 +### 增强对非穷尽枚举的 `switch` 支持 -新增对非穷尽枚举使用 `switch` 语句的支持,提高枚举处理的灵活性,支持未知枚举值的处理,增强代码的健壮性。 +新增对非穷尽枚举使用 `switch` 语句的支持,提高了枚举处理的灵活性,能够更好地处理未知枚举值,增强代码的健壮性。 -### 允许对布尔向量使用更多运算符 +### 扩展布尔向量运算符支持 布尔向量现在支持更多运算符,包括逻辑运算和比较运算。 ### 内联汇编:类型化的破坏描述符 -内联汇编现在支持类型化的 clobber 列表,提供更好的类型安全。 +内联汇编现在支持类型化的 `clobber` 列表,提供了更好的类型安全保证。 -### 指针转换增强 +### 指针转换能力增强 -`@ptrCast` 现在允许从单项指针到切片的转换,提供更大的灵活性。 +`@ptrCast` 现在允许从单项指针转换为切片,提供了更大的灵活性。 -### undefined 运算新规则 +### 调整 `undefined` 运算规则 -对 `undefined` 值的算术运算规则发生了变化,任何与 `undefined` 的运算都返回 `undefined`。 +对 `undefined` 值的算术运算规则有所调整,任何与 `undefined` 的运算结果都将返回 `undefined`。 -### 有损转换检测 +### 加强有损转换检测 -现在对于可能导致精度损失的整数到浮点数转换会发出编译错误。 +对于可能导致精度损失的整数到浮点数转换,编译器会视为错误。 ## 标准库重大变更 @@ -80,6 +81,7 @@ aarch64 后端的开发也在稳步推进,持续改进 ARM 平台支持,为 ### 格式化系统调整 格式化系统进行了重要调整: + - 调用自定义 `format` 方法需要使用 `{f}` 格式说明符 - `format` 方法签名简化,移除了格式字符串和选项参数 - 格式化打印不再处理 Unicode @@ -88,12 +90,13 @@ aarch64 后端的开发也在稳步推进,持续改进 ARM 平台支持,为 ### `ArrayList` 非托管化 容器类型的重要变更: + - `std.ArrayList` 现在默认采用非托管方式 - 开发者需要显式提供分配器 - 与其他非托管容器保持一致 - 提供更好的内存管理控制 -### 去泛型化链表 +### 链表去泛型化 链表类型进行了重构,去除了泛型化设计。 @@ -117,11 +120,12 @@ aarch64 后端的开发也在稳步推进,持续改进 ARM 平台支持,为 ### 移除隐式根模块 -构建系统移除了对隐式根模块的支持,需要在构建脚本中明确指定模块,提高构建配置的明确性。 +构建系统移除了对隐式根模块的支持,现在需要在构建脚本中明确指定模块;这提高了构建配置的清晰度和准确性。 ### macOS 文件系统监视 在 macOS 上新增了文件系统监视功能: + - 能够在文件更改时自动触发重建 - 支持 `--watch` 和 `--debounce` 选项 - 显著提高开发效率 @@ -130,19 +134,21 @@ aarch64 后端的开发也在稳步推进,持续改进 ARM 平台支持,为 构建系统现在支持 Web 界面和详细的时间报告功能。 -## 模糊测试器 +### 模糊测试器 Zig 0.15.1 集成了一个内置的模糊测试器: + - 支持进程内模糊测试 - 提供 Web UI 界面 - 支持实时代码覆盖率显示 -- 可以快速发现代码中的问题 +- 可以快速发现代码中的潜在问题 ## 工具链更新 ### LLVM 20 升级到 LLVM 20,带来了: + - 更好的优化支持 - 新的目标架构支持 - 改进的调试信息生成 @@ -158,22 +164,24 @@ Zig 0.15.1 集成了一个内置的模糊测试器: ### MinGW-w64 更新 -MinGW-w64 工具链得到了更新,改进了 Windows 交叉编译支持。 +MinGW-w64 工具链得到了更新,进一步改进了对 Windows 的交叉编译支持。 ### zig libc 和 zig cc 增强 -`zig libc` 和 `zig cc` 命令得到了功能增强: +`zig libc` 和 `zig cc` 命令的功能得到了增强: + - 更好的 GCC 兼容性 - 支持更多编译选项 -- 更好的错误报告 +- 更清晰的错误报告 ## 版本跳跃说明 -Zig 官方团队选择直接从 `0.14.0` 跳跃到 `0.15.1`,这反映了: -- 本次更新包含的重大变更数量 +Zig 官方团队选择直接从 `0.14.0` 跳跃到 `0.15.1`,这一决策反映了: + +- 本次更新包含的重大变更数量之多 - 对编译器性能的重要改进 - 标准库接口的重大重构 -- 为未来版本奠定更好的基础 +- 为未来版本奠定更坚实的基础 ## 升级挑战与机遇 @@ -194,6 +202,7 @@ Zig 官方团队选择直接从 `0.14.0` 跳跃到 `0.15.1`,这反映了: ## 社区影响 这次更新对 Zig 社区产生了重要影响: + - **学习曲线**:新用户需要适应新的接口设计 - **迁移工作**:现有项目需要进行大量调整 - **性能收益**:编译速度的显著提升改善开发体验 @@ -202,14 +211,16 @@ Zig 官方团队选择直接从 `0.14.0` 跳跃到 `0.15.1`,这反映了: ## 技术债务清理 本次更新体现了 Zig 团队对技术债务的积极清理: + - 移除了有争议的 `usingnamespace` 特性 - 重构了性能不佳的 I/O 接口 - 统一了容器类型的设计理念 -- 为未来的语言演进奠定基础 +- 为未来的语言演进奠定坚实基础 ## 未来展望 `0.15.1` 为 Zig 的未来发展奠定了重要基础: + - **编译性能**:为大型项目开发提供更好支持 - **接口设计**:更一致、更高效的标准库 - **开发体验**:更快的编译和更好的工具支持 @@ -224,9 +235,10 @@ I/O 系统将继续作为接口进行发展和完善,为未来的异步编程 ## 建议 对于 Zig 开发者: + 1. **谨慎升级**:在测试环境中充分验证 2. **分步迁移**:逐步调整代码以适配新接口 -3. **利用性能**:充分利用编译速度的改进 -4. **关注社区**:参与社区讨论,分享迁移经验 +3. **充分利用性能优势**:积极采用有关编译速度的改进 +4. **关注社区动态**:参与社区讨论,分享迁移经验和最佳实践 -`0.15.1` 是 Zig 发展历程中的一个重要里程碑,虽然带来了较多的破坏性更改,但为语言的长期发展和性能提升奠定了坚实的基础。这是语言稳定化的最后防线,为 1.0 版本的发布做好了准备。 \ No newline at end of file +`0.15.1` 是 Zig 发展历程中的一个重要里程碑,虽然带来了较多的破坏性变更,但为语言的长期发展和性能提升奠定了坚实的基础。这标志着语言稳定化的最后阶段,为 1.0 版本的正式发布做好了充分准备。 diff --git a/course/update/upgrade-0.15.1.md b/course/update/upgrade-0.15.1.md index 11ed0714..2d23a896 100644 --- a/course/update/upgrade-0.15.1.md +++ b/course/update/upgrade-0.15.1.md @@ -4,14 +4,13 @@ showVersion: false --- 本篇文档将介绍如何从 `0.14.0` 版本升级到 `0.15.1`。 - -> 本次发布包含了 162 位贡献者在 5 个月内完成的 647 次提交。在默认选择 Zig 的 x86 后端后,调试编译速度提高了 5 倍;正在开发的 aarch64 后端也紧随其后。同时,Writergate 事件以及一系列语言变更和标准库的调整,带来了大量的 API 破坏性更改。 +本次发布凝聚了 162 位贡献者 在 5 个月内 647 次提交的成果。在将 Zig 的 **x86 后端** 设为 **调试模式** 的默认选项后,其编译速度提升了 5 倍;同时,正在积极开发的 **aarch64 后端** 也取得了显著进展。此外,**Writergate** 以及一系列语言变更和标准库调整,带来了大量的 **API 破坏性更改**。 ## 语言变更 ### 移除 `usingnamespace` -`usingnamespace` 关键字已被移除。以下是一些常见用例的替代方案: +`usingnamespace` 关键字已被移除。以下是常见用例的替代方案: #### 用例:条件包含 @@ -50,10 +49,10 @@ pub const write = os_impl.write; // 旧代码 const MyStruct = struct { data: u32, - - usingnamespace if (builtin.mode == .Debug) + + usingnamespace if (builtin.mode == .Debug) @import("debug_impl.zig") - else + else @import("release_impl.zig"); }; ``` @@ -62,18 +61,18 @@ const MyStruct = struct { ```zig // 新代码 -const Impl = if (builtin.mode == .Debug) +const Impl = if (builtin.mode == .Debug) @import("debug_impl.zig") -else +else @import("release_impl.zig"); const MyStruct = struct { data: u32, - + pub fn doSomething(self: *MyStruct) void { return Impl.doSomething(self); } - + // 显式实现所有需要的方法 }; ``` @@ -110,9 +109,9 @@ fn LoggingMixin(comptime T: type) type { const MyStruct = struct { data: u32, - + const Mixin = LoggingMixin(@This()); - + pub fn log(self: *MyStruct, message: []const u8) void { Mixin.log(self, message); } @@ -165,7 +164,7 @@ fn handleEnum(value: MyEnum) void { test "boolean vector operations" { const vec_a: @Vector(4, bool) = .{ true, false, true, false }; const vec_b: @Vector(4, bool) = .{ false, true, true, false }; - + const and_result = vec_a & vec_b; const or_result = vec_a | vec_b; const xor_result = vec_a ^ vec_b; @@ -205,10 +204,10 @@ asm volatile ("mov %[src], %[dst]" test "ptrCast to slice" { var value: u32 = 42; const ptr: *u32 = &value; - + // 新功能:将单项指针转换为切片 const slice: []u32 = @ptrCast(ptr); - + std.testing.expect(slice[0] == 42); } ``` @@ -221,11 +220,11 @@ test "ptrCast to slice" { test "undefined arithmetic" { const a: i32 = undefined; const b: i32 = 10; - + // 任何与 undefined 的运算都返回 undefined const result = a + b; // result 是 undefined _ = result; - + // 更安全的做法 const safe_a: i32 = 0; // 显式初始化 const safe_result = safe_a + b; @@ -240,13 +239,13 @@ test "undefined arithmetic" { ```zig test "lossy integer to float conversion" { const large_int: u64 = 0x1FFFFFFFFFFFFF; // 53 位 - + // 这将产生编译错误,因为 f64 只有 52 位尾数 // const float_val: f64 = @floatFromInt(large_int); // 错误! - + // 需要显式使用有损转换 const float_val: f64 = @floatFromInt(@as(u53, @truncate(large_int))); - + std.debug.print("Float: {}\n", .{float_val}); } ``` @@ -260,6 +259,7 @@ test "lossy integer to float conversion" { #### 动机 旧的 I/O 系统存在以下问题: + - 泛型接口导致编译时间过长 - 缓冲区管理不一致 - 性能不佳,存在不必要的内存拷贝 @@ -306,26 +306,26 @@ try processData( ); ``` -#### 新的 `std.Io.Writer` 和 `std.Io.Reader` API +### 新的 `std.Io.Writer` 和 `std.Io.Reader` API -新的 API 采用非泛型设计: +新的 API 采用**非泛型设计**: ```zig // std.Io.Writer 的定义 pub const Writer = struct { ptr: *anyopaque, vtable: *const VTable, - + pub const VTable = struct { write: *const fn (*anyopaque, []const u8) anyerror!usize, writeAll: *const fn (*anyopaque, []const u8) anyerror!void, writeByte: *const fn (*anyopaque, u8) anyerror!void, }; - + pub fn write(self: Writer, bytes: []const u8) !usize { return self.vtable.write(self.ptr, bytes); } - + pub fn writeAll(self: Writer, bytes: []const u8) !void { return self.vtable.writeAll(self.ptr, bytes); } @@ -453,7 +453,7 @@ var buffered_writer = std.io.BufferedWriter(4096, @TypeOf(base_writer)).init(bas const Point = struct { x: f32, y: f32, - + pub fn format(self: Point, writer: anytype) !void { try writer.print("Point({d}, {d})", .{ self.x, self.y }); } @@ -473,7 +473,7 @@ std.debug.print("{f}\n", .{point}); // 注意使用 {f} const Point = struct { x: f32, y: f32, - + pub fn format( self: Point, comptime fmt: []const u8, // 被移除 @@ -494,7 +494,7 @@ const Point = struct { const Point = struct { x: f32, y: f32, - + pub fn format( self: Point, writer: anytype, // 只保留 writer 参数 @@ -538,14 +538,14 @@ std.debug.print("{b}\n", .{value}); // 二进制:11111111 // 浮点数格式化 const pi: f64 = 3.14159; std.debug.print("{d:.2}\n", .{pi}); // 保留两位小数:3.14 -std.debug.print("{e}\n", .{pi}); // 科学计数法:3.14159e+00 +std.debug.print("{e}\n", .{pi}); // 科学计数法:3.14159e+00 // 指针和切片 const ptr: *u32 = &value; const slice: []const u8 = "hello"; -std.debug.print("{*}\n", .{ptr}); // 指针地址 -std.debug.print("{s}\n", .{slice}); // 字符串 -std.debug.print("{any}\n", .{slice}); // 通用格式化 +std.debug.print("{*}\n", .{ptr}); // 指针地址 +std.debug.print("{s}\n", .{slice}); // 字符串 +std.debug.print("{any}\n", .{slice}); // 通用格式化 ``` ### 去泛型化链表 @@ -593,26 +593,26 @@ pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer _ = gpa.deinit(); const allocator = gpa.allocator(); - + var client = std.http.Client{ .allocator = allocator }; defer client.deinit(); - + const uri = std.Uri.parse("https://httpbin.org/get") catch unreachable; - + var headers = std.http.Headers{ .allocator = allocator }; defer headers.deinit(); - + try headers.append("User-Agent", "Zig HTTP Client"); - + var request = try client.open(.GET, uri, headers, .{}); defer request.deinit(); - + try request.send(.{}); try request.wait(); - + const body = try request.reader().readAllAlloc(allocator, 8192); defer allocator.free(body); - + std.debug.print("Response: {s}\n", .{body}); } ``` @@ -629,20 +629,20 @@ pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer _ = gpa.deinit(); const allocator = gpa.allocator(); - + const address = try std.net.Address.parseIp("93.184.216.34", 443); // example.com const stream = try std.net.tcpConnectToAddress(address); defer stream.close(); - + var tls_client = try std.crypto.tls.Client.init(stream, .{ .host = "example.com", .allocator = allocator, }); defer tls_client.deinit(); - + const request = "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n"; try tls_client.writeAll(request); - + var buffer: [4096]u8 = undefined; const bytes_read = try tls_client.read(&buffer); std.debug.print("Response: {s}\n", .{buffer[0..bytes_read]}); @@ -651,7 +651,7 @@ pub fn main() !void { ### `ArrayList`:将非托管模式设为默认 -这是一个重大的破坏性更改。`std.ArrayList` 现在默认采用非托管 (unmanaged) 方式: +这是一个重大的破坏性更改。`std.ArrayList` 现在默认采用 **非托管(unmanaged)** 模式: ```zig // 旧代码 @@ -660,10 +660,10 @@ const std = @import("std"); fn oldArrayListExample(allocator: std.mem.Allocator) !void { var list = std.ArrayList(i32).init(allocator); defer list.deinit(); - + try list.append(42); try list.appendSlice(&[_]i32{ 1, 2, 3 }); - + for (list.items) |item| { std.debug.print("{d} ", .{item}); } @@ -680,10 +680,10 @@ fn newArrayListExample(allocator: std.mem.Allocator) !void { // 方式 1:使用新的 ArrayListUnmanaged var list: std.ArrayListUnmanaged(i32) = .empty; defer list.deinit(allocator); - + try list.append(allocator, 42); try list.appendSlice(allocator, &[_]i32{ 1, 2, 3 }); - + for (list.items) |item| { std.debug.print("{d} ", .{item}); } @@ -695,7 +695,7 @@ fn compatibilityExample(allocator: std.mem.Allocator) !void { const ArrayList = std.ArrayListUnmanaged; var list: ArrayList(i32) = .empty; defer list.deinit(allocator); - + try list.append(allocator, 42); } @@ -703,11 +703,11 @@ fn compatibilityExample(allocator: std.mem.Allocator) !void { fn newInitExample(allocator: std.mem.Allocator) !void { var list = std.ArrayList(i32).init(allocator); // 仍然可用,但已弃用 defer list.deinit(); - + // 或者使用新的方式 var new_list: std.ArrayList(i32) = .{}; defer new_list.deinit(allocator); - + try new_list.append(allocator, 42); } ``` @@ -839,15 +839,15 @@ zig build --watch zig build --watch --debounce 100 ``` -### Web 界面和时间报告 +### Web 界面和即时报告 -构建系统现在支持 Web 界面和详细的时间报告功能。 +构建系统现在支持 Web 界面和详细的即时报告功能。 ## 编译器 ### x86 后端 -在默认选择 Zig 的 x86 后端的情况下,调试编译速度提高了 5 倍。这是本次更新最显著的性能改进: +在 **调试编译** 默认为 **x86 后端** 的情况下,其速度提高了 5 倍。这也是本次更新最显著的性能改进: ```bash # 使用新的 x86 后端(默认) @@ -859,7 +859,7 @@ zig build -Doptimize=Debug -fLLVM ### aarch64 后端 -aarch64 后端的开发也在稳步推进,为 ARM 平台提供更好的支持。 +**aarch64 后端** 的开发也在稳步推进,为 ARM 平台提供更好的支持。 ### 增量编译 @@ -968,10 +968,10 @@ zig build test --fuzz --timeout 60 // 模糊测试例子 test "fuzz string parsing" { const input_bytes = std.testing.fuzzInput(.{}); - + // 测试字符串解析函数 const result = parseString(input_bytes); - + // 确保不会崩溃 _ = result catch |err| { // 预期的错误可以忽略 @@ -991,7 +991,7 @@ fn parseString(input: []const u8) ![]const u8 { 本次发布修复了大量错误。 -### 本次发布包含的错误 +## 本次发布包含的错误 Zig 目前仍存在一些已知的 bugs,包括一些编译错误。 @@ -1000,6 +1000,7 @@ Zig 目前仍存在一些已知的 bugs,包括一些编译错误。 ### LLVM 20 本次更新升级到 LLVM 20,带来了以下改进: + - 更好的优化支持 - 新的目标架构支持 - 改进的调试信息生成 @@ -1110,16 +1111,16 @@ I/O 系统将继续作为接口进行发展和完善。 - 最后处理 ArrayList 等容器的变更 3. **使用编译器检查**: + ```bash # 检查编译错误 zig build-exe src/main.zig - + # 使用新的 x86 后端加速编译 zig build -fno-LLVM ``` 4. **测试全面性**:确保所有功能在新版本下正常运行 - 5. **利用新特性**: - 使用新的 x86 后端提高编译速度 - 使用文件系统监视功能 @@ -1139,4 +1140,4 @@ I/O 系统将继续作为接口进行发展和完善。 - 新的性能改进主要体现在编译速度上 - 文件系统监视功能有助于提高开发效率 -完整的发布说明可在 [Zig 官方网站](https://ziglang.org/download/0.15.1/release-notes.html) 查看。 \ No newline at end of file +完整的发布说明可在 [Zig 官方网站](https://ziglang.org/download/0.15.1/release-notes.html) 查看。 From 8f5be54e439126312ad475b033aca32f87c7aad4 Mon Sep 17 00:00:00 2001 From: jinzhongjia Date: Sun, 21 Sep 2025 18:43:41 +0800 Subject: [PATCH 3/4] =?UTF-8?q?chore(version):=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=E8=AF=BE=E7=A8=8B=E6=96=87=E6=A1=A3=20Zig=20=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E8=87=B3=200.15.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 将版本号从 0.14.0 更新至 0.15.1 - 同步文档配置中的版本信息 --- course/.vitepress/theme/config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/course/.vitepress/theme/config.ts b/course/.vitepress/theme/config.ts index b1e7a486..49d49919 100644 --- a/course/.vitepress/theme/config.ts +++ b/course/.vitepress/theme/config.ts @@ -1,3 +1,3 @@ -const version: string = "0.14.0"; +const version: string = "0.15.1"; export { version }; From 08ad4616de6041e47bc27d6fcd9ca085ba8df339 Mon Sep 17 00:00:00 2001 From: jinzhongjia Date: Sun, 21 Sep 2025 23:27:31 +0800 Subject: [PATCH 4/4] =?UTF-8?q?docs(course/update):=20=E6=9B=B4=E6=96=B0?= =?UTF-8?q?=20Zig=200.15.1=20=E6=96=87=E6=A1=A3=E4=B8=AD=20ArrayList=20?= =?UTF-8?q?=E9=9D=9E=E6=89=98=E7=AE=A1=E6=A8=A1=E5=BC=8F=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 调整 `ArrayList` 非托管模式部分文本格式 - 更正非托管模式括号间距 - 保持文档描述的准确性和一致性 --- course/update/upgrade-0.15.1.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/course/update/upgrade-0.15.1.md b/course/update/upgrade-0.15.1.md index 2d23a896..b7d979e7 100644 --- a/course/update/upgrade-0.15.1.md +++ b/course/update/upgrade-0.15.1.md @@ -651,7 +651,7 @@ pub fn main() !void { ### `ArrayList`:将非托管模式设为默认 -这是一个重大的破坏性更改。`std.ArrayList` 现在默认采用 **非托管(unmanaged)** 模式: +这是一个重大的破坏性更改。`std.ArrayList` 现在默认采用 **非托管 (unmanaged)** 模式: ```zig // 旧代码