Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 29 additions & 23 deletions course/code/16/hello_world.zig
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
pub fn main(init: std.process.Init) !void {
// 三个 struct 各自包含一段文档片段,每段都是可以直接粘贴进 src/main.zig 的完整程序。
// 因此 std 的导入放在各 struct 内部,文件级不能再有 `const std`(否则 ambiguous reference)。
pub fn main(init: @import("std").process.Init) !void {
try One.main();
try Two.main(init.io);
try Three.main(init.io);
try Two.main(init);
try Three.main(init);
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

const std = @import("std");

const One = struct {
// #region one
const std = @import("std");

pub fn main() !void {
std.debug.print("Hello, World!\n", .{});
}
Expand All @@ -16,43 +18,47 @@ const One = struct {

const Two = struct {
// #region two
pub fn main(io: std.Io) !void {
var stdout_buffer: [1024]u8 = undefined;
var stdout_writer = std.Io.File.stdout().writer(io, &stdout_buffer);
const std = @import("std");

pub fn main(init: std.process.Init) !void {
const io = init.io;

// 传入长度为 0 的缓冲区,表示不缓冲,每次 print 都直接写出
var stdout_writer = std.Io.File.stdout().writer(io, &.{});
const stdout = &stdout_writer.interface;

var stderr_buffer: [1024]u8 = undefined;
var stderr_writer = std.Io.File.stderr().writer(io, &stderr_buffer);
var stderr_writer = std.Io.File.stderr().writer(io, &.{});
const stderr = &stderr_writer.interface;

try stdout.print("Hello {s}!\n", .{"out"});
try stderr.print("Hello {s}!\n", .{"err"});

try stdout.flush();
try stderr.flush();
} // #endregion two
}
// #endregion two
};

const Three = struct {
// #region three
pub fn main(io: std.Io) !void {
const std = @import("std");

pub fn main(init: std.process.Init) !void {
const io = init.io;

// 定义两个缓冲区
var stdout_buffer: [1024]u8 = undefined; // [!code focus]
var stderr_buffer: [1024]u8 = undefined; // [!code focus]

// 获取writer句柄// [!code focus]
var stdout_writer = std.Io.File.stdout().writer(io, &stdout_buffer);
// 获取 writer 句柄
var stdout_writer = std.Io.File.stdout().writer(io, &stdout_buffer); // [!code focus]
const stdout = &stdout_writer.interface;

// 获取writer句柄// [!code focus]
var stderr_writer = std.Io.File.stderr().writer(io, &stderr_buffer);
var stderr_writer = std.Io.File.stderr().writer(io, &stderr_buffer); // [!code focus]
const stderr = &stderr_writer.interface;

// 通过句柄写入buffer// [!code focus]
try stdout.print("Hello {s}!\n", .{"out"}); // [!code focus]
try stderr.print("Hello {s}!\n", .{"err"}); // [!code focus]
// 通过句柄写入 buffer
try stdout.print("Hello {s}!\n", .{"out"});
try stderr.print("Hello {s}!\n", .{"err"});

// 尝试刷新buffer// [!code focus]
// 把 buffer 中的内容真正刷出去
try stdout.flush(); // [!code focus]
try stderr.flush(); // [!code focus]
}
Expand Down
52 changes: 29 additions & 23 deletions course/code/release/hello_world.zig
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
pub fn main(init: std.process.Init) !void {
// 三个 struct 各自包含一段文档片段,每段都是可以直接粘贴进 src/main.zig 的完整程序。
// 因此 std 的导入放在各 struct 内部,文件级不能再有 `const std`(否则 ambiguous reference)。
pub fn main(init: @import("std").process.Init) !void {
try One.main();
try Two.main(init.io);
try Three.main(init.io);
try Two.main(init);
try Three.main(init);
}

const std = @import("std");

const One = struct {
// #region one
const std = @import("std");

pub fn main() !void {
std.debug.print("Hello, World!\n", .{});
}
Expand All @@ -16,43 +18,47 @@ const One = struct {

const Two = struct {
// #region two
pub fn main(io: std.Io) !void {
var stdout_buffer: [1024]u8 = undefined;
var stdout_writer = std.Io.File.stdout().writer(io, &stdout_buffer);
const std = @import("std");

pub fn main(init: std.process.Init) !void {
const io = init.io;

// 传入长度为 0 的缓冲区,表示不缓冲,每次 print 都直接写出
var stdout_writer = std.Io.File.stdout().writer(io, &.{});
const stdout = &stdout_writer.interface;

var stderr_buffer: [1024]u8 = undefined;
var stderr_writer = std.Io.File.stderr().writer(io, &stderr_buffer);
var stderr_writer = std.Io.File.stderr().writer(io, &.{});
const stderr = &stderr_writer.interface;

try stdout.print("Hello {s}!\n", .{"out"});
try stderr.print("Hello {s}!\n", .{"err"});

try stdout.flush();
try stderr.flush();
} // #endregion two
}
// #endregion two
};

const Three = struct {
// #region three
pub fn main(io: std.Io) !void {
const std = @import("std");

pub fn main(init: std.process.Init) !void {
const io = init.io;

// 定义两个缓冲区
var stdout_buffer: [1024]u8 = undefined; // [!code focus]
var stderr_buffer: [1024]u8 = undefined; // [!code focus]

// 获取writer句柄// [!code focus]
var stdout_writer = std.Io.File.stdout().writer(io, &stdout_buffer);
// 获取 writer 句柄
var stdout_writer = std.Io.File.stdout().writer(io, &stdout_buffer); // [!code focus]
const stdout = &stdout_writer.interface;

// 获取writer句柄// [!code focus]
var stderr_writer = std.Io.File.stderr().writer(io, &stderr_buffer);
var stderr_writer = std.Io.File.stderr().writer(io, &stderr_buffer); // [!code focus]
const stderr = &stderr_writer.interface;

// 通过句柄写入buffer// [!code focus]
try stdout.print("Hello {s}!\n", .{"out"}); // [!code focus]
try stderr.print("Hello {s}!\n", .{"err"}); // [!code focus]
// 通过句柄写入 buffer
try stdout.print("Hello {s}!\n", .{"out"});
try stderr.print("Hello {s}!\n", .{"err"});

// 尝试刷新buffer// [!code focus]
// 把 buffer 中的内容真正刷出去
try stdout.flush(); // [!code focus]
try stderr.flush(); // [!code focus]
}
Expand Down
10 changes: 8 additions & 2 deletions course/hello-world.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,14 +60,16 @@ Zig 本身没有内置的 `@print()` 函数,输出功能通常由标准库的

:::info 🅿️ 提示
`main` 函数的返回类型 `!void` 是一个错误联合类型。它表示该函数要么成功执行并返回 `void`(即无返回值),要么返回一个错误。

`main` 的参数 `init: std.process.Init` 是入口函数可选的参数形式,它携带了运行时的初始化信息,其中的 `init.io` 就是我们做 I/O 所需要的 `Io` 实例。
:::

这段代码分别向 `stdout` 和 `stderr` 输出了信息。

- `stdout` (标准输出):用于输出程序的正常信息。写入 `stdout` 的操作可能会失败。
- `stderr` (标准错误):用于输出错误信息。写入 `stderr` 同样可能失败,因此示例里也使用了 `try` 来处理错误。

我们通过 `std.Io.File.stdout()` 和 `std.Io.File.stderr()` 获取标准输出和标准错误,并基于传入的 `io` 实例创建 `writer`。示例中的 `io` 一般来自入口函数 `main(init: std.process.Init)` 中的 `init.io`
我们通过 `std.Io.File.stdout()` 和 `std.Io.File.stderr()` 获取标准输出和标准错误,再基于 `io` 创建各自的 `writer`。这里传入的缓冲区是空的(`&.{}`),意味着不做缓冲——每一次 `print` 都会直接写出去

### 考虑性能:使用缓冲区

Expand All @@ -77,7 +79,11 @@ Zig 本身没有内置的 `@print()` 函数,输出功能通常由标准库的

<<<@/code/release/hello_world.zig#three

这里直接为 `stdout` 和 `stderr` 各自提供了一块固定缓冲区,`writer` 会先把内容写入缓冲区,再在 `flush` 时真正输出,从而减少系统调用。
与上一段代码的区别只在于:这里为 `stdout` 和 `stderr` 各自提供了一块 1024 字节的缓冲区。`writer` 会先把内容写入缓冲区,直到缓冲区满或者调用 `flush` 时才真正输出,从而减少系统调用的次数。

::: warning ⚠️ 注意
使用缓冲区后,**必须记得 `flush`**,否则程序结束时缓冲区里尚未写出的内容就丢失了。
:::

## 更进一步:线程安全

Expand Down
Loading