Skip to content

Commit

Permalink
更新hello world
Browse files Browse the repository at this point in the history
  • Loading branch information
jinzhongjia committed Sep 13, 2023
1 parent 624b48f commit e816d0d
Showing 1 changed file with 58 additions and 1 deletion.
59 changes: 58 additions & 1 deletion learn/basic/hello-world.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub fn main() void {

_很简单,不是吗?_

## 说明
## 简单说明

以上程序中,我们先通过 `@import` 这个内置函数(在zig中有很多的内置函数,它们都以`@`开头,并且遵循[小驼峰命名法](#))引入了 zig 的标准库。

Expand All @@ -32,3 +32,60 @@ zig 会自动为我们根据后面的参量表推导出对应的类型,当 zig

你是不是觉得自己被耍了?别担心,上面仅仅只是一个示例而已,来为你演示一下 zig 的使用!
:::

## 换一种方式?

接下来,让我们换一种方式来讲述如何“正确”地使用 zig 打印出“Hello, World!”,不要认为这是一个简单的问题,这涉及到计算机相当底层的涉及哲学。

首先,我要告诉你,zig 并没有一个内置的打印功能,包含“输出”功能的包只有 `log` 包和 `debug` 包,zig 并没有内置类似与 `@print()` 这种函数。再来一个简单的例子告诉你,如何打印东西(**_但是请记住,以下示例代码不应用于生产环境中_**)。

```zig
const std = @import("std");
pub fn main() !void {
var out = std.io.getStdOut().writer();
var err = std.io.getStdErr().writer();
try out.print("Hello {s}!\n", .{"out"});
try err.print("Hello {s}!\n", .{"err"});
}
```

这段代码将会分别输出 `Hello out!``Hello err!`,这里我需要向你讲述一下 `stdout``stderr` ,它们均是抽象的io(input and output)流句柄(关于流这个概念可能不好解释,你暂时就当作向水流一样的数据的就行)。`stdout` 用于正常的输出,它可能会出现错误导致写入失败。`stderr` 用于错误输出,我们假定 `stderr` 一定不会失败(这个是操作系统负责保证的),这就是它们的区别。

通过 `io` 命名空间(或者称之为包)获取到了标准输出和错误输出的 `writer` 句柄,这个句柄实现流`print`函数,我们只需要正常打印即可!

接下来加深一点难度,你有没有想过,这些`print`函数是如何实现的?

它们都是依靠系统调用来实现输出效果,但是这就面临着性能问题,我们知道系统调用会造成内核上下文切换的开销(系统调用的流程:执行系统调用,此时控制权会切换回内核,由内核执行完成进程需要的系统调用函数后再将控制权返回给进程),所以我们如何解决这个问题呢?可以增加一个缓冲区,等到要打印的内容都到一定程度后再一次性全部 `print`,那么此时的解决方式就如下:

```zig
const std = @import("std");
pub fn main() !void {
var out = std.io.getStdOut().writer();
var err = std.io.getStdErr().writer();
// 获取buffer
var out_buffer = std.io.bufferedWriter(out);
var err_buffer = std.io.bufferedWriter(err);
// 获取writer句柄
var out_writer = out_buffer.writer();
var err_writer = err_buffer.writer();
// 通过句柄写入buffer
try out_writer.print("Hello {s}!\n", .{"out"});
try err_writer.print("Hello {s}!\n", .{"err"});
// 尝试刷新buffer
try out_buffer.flush();
try err_buffer.flush();
}
```

此时我们就分别得到了使用缓冲区的 `stdout``stderr`, 性能更高了!

## 再进一步?

TODO

0 comments on commit e816d0d

Please sign in to comment.