Skip to content

Commit 8bef233

Browse files
committed
build: 更新格式化脚本,移除 zig fmt
1 parent f0f87d7 commit 8bef233

9 files changed

Lines changed: 106 additions & 22 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@ zig-cache
1313
.direnv
1414
PDF
1515
.DS_Store
16+
.sisyphus/plans

course/advanced/atomic.md

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ outline: deep
66

77
> 原子操作是在多线程环境中非常重要的一个概念,原子操作是指一个或一系列的操作,它们作为一个整体来执行,中间不会被任何其他的操作打断。这意味着原子操作要么全部完成,要么全部不完成,不会出现只完成部分操作的情况。
88
9-
目前 zig 提供了一些内建函数来进行原子操作,并且提供了 `std.atomic` 命名空间来实现内存排序、原子数据结构。
9+
目前 Zig 提供了一些内建函数来进行原子操作,并且提供了 `std.atomic` 命名空间来实现内存排序、原子数据结构。
1010

1111
> [!TIP]
1212
> 该部分内容更适合在单片机或者某些系统级组件开发上使用,常规使用可以使用 `std.Thread` 命名空间下的类型,包含常规的 `Mutex``Condition``ResetEvent``WaitGroup`等等。
@@ -122,7 +122,12 @@ outline: deep
122122

123123
<<<@/code/release/atomic.zig#atomic_value
124124

125-
TODO: 增加适当的讲解
125+
上述代码展示了一个典型的 **引用计数(Reference Counting)** 模式实现。引用计数是一种常见的内存管理技术,用于追踪有多少个引用指向同一个对象。
126+
127+
- **`ref()` 方法**:使用 `.monotonic` 顺序递增计数器。由于只是简单地增加计数,不需要与其他内存操作建立同步关系。
128+
- **`unref()` 方法**:使用 `.release` 顺序递减计数器,确保在计数递减之前的所有内存操作对其他线程可见。当计数减到 1 时,使用 `.acquire` 加载来获取之前所有 `unref()` 操作形成的 release 序列,确保可以安全地调用清理函数。
129+
130+
这种模式常用于智能指针、共享资源管理等场景,是替代 `Mutex` 的轻量级线程安全方案
126131

127132
### `spinLoopHint` 自旋锁
128133

@@ -134,4 +139,19 @@ TODO: 增加适当的讲解
134139

135140
<<<@/code/release/atomic.zig#spinLoopHint
136141

137-
TODO:增加更多的讲解,例如使用示例,原子级别讲解等!
142+
`spinLoopHint` 用于在自旋等待循环中向 CPU 发出提示信号,表明当前线程正处于忙等待状态。这允许处理器进行功耗优化或将资源让给其他硬件线程。
143+
144+
**何时使用 `spinLoopHint`**
145+
146+
- 当你实现自旋锁或其他忙等待逻辑时
147+
- 当等待某个原子变量的值发生变化时
148+
- 当预期等待时间非常短(纳秒到微秒级别)时
149+
150+
**与 Mutex 的选择**
151+
152+
- **自旋等待**:适合极短时间的等待,避免线程上下文切换的开销
153+
- **Mutex**:适合等待时间不确定或较长的场景,会让出 CPU 给其他线程
154+
155+
::: warning ⚠️ 警告
156+
不当使用自旋等待会导致 CPU 资源浪费。如果等待时间较长或不确定,应使用 `std.Thread.Mutex` 等同步原语。
157+
:::

course/advanced/interact-with-c.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,22 +4,22 @@ outline: deep
44

55
# 与 C 交互
66

7-
zig 作为一个可以独立于 C 的语言,不依赖 libc,但 zig 仍然具有非常强大的与 C 直接交互的能力,并远超其他语言。
7+
Zig 作为一个可以独立于 C 的语言,不依赖 libc,但 Zig 仍然具有非常强大的与 C 直接交互的能力,并远超其他语言。
88

99
> [!TIP] 什么是 libc
1010
> libc 是 C 语言的标准库,它提供了许多基本的程序功能,如输入 / 输出处理、字符串操作、内存管理等。在 Unix 和 Linux 系统中,libc 通常是操作系统的核心部分,它提供了系统调用的接口,使得应用程序可以使用操作系统的服务。在 Windows 系统中,类似的库是 msvcrt 库。
1111
1212
::: info 🅿️ 提示
1313

14-
zig 所指的交互并不仅仅是使用 C 的库,zig 还可以作为 C 的编译器,导出 C ABI 兼容的库供其他程序使用。
14+
Zig 所指的交互并不仅仅是使用 C 的库,Zig 还可以作为 C 的编译器,导出 C ABI 兼容的库供其他程序使用。
1515

16-
并且 zig 使用 C 并不是通过 [FFI](https://en.wikipedia.org/wiki/Foreign_function_interface) / bindings 实现,而是近乎原生的调用,这归功于 zig 实现了一套 C 的 [编译器](https://github.com/ziglang/zig/tree/master/lib/compiler/aro) 并且支持将 C 代码翻译为 zig 代码!
16+
并且 Zig 使用 C 并不是通过 [FFI](https://en.wikipedia.org/wiki/Foreign_function_interface) / bindings 实现,而是近乎原生的调用,这归功于 Zig 实现了一套 C 的 [编译器](https://github.com/ziglang/zig/tree/master/lib/compiler/aro) 并且支持将 C 代码翻译为 Zig 代码!
1717

1818
:::
1919

2020
## C ABI 类型
2121

22-
zig 定义了几个对应 C ABI 的基本类型:
22+
Zig 定义了几个对应 C ABI 的基本类型:
2323

2424
- `c_char`
2525
- `c_short`
@@ -67,7 +67,7 @@ C 语言共享类型通常是通过引入头文件实现,这点在 zig 中可
6767
6868
既然可以引入头文件,那么毫无疑问同样可以引入由第三方写好的二进制 lib 库。
6969

70-
以微软开发的跨平台开源 c/c++ 包管理器 _vcpkg_ 的库导入为例,具体安装以及设置环境变量的教程不在这里赘叙,只讲怎么 zig 使用已经编译好的 lib。
70+
以微软开发的跨平台开源 c/c++ 包管理器 _vcpkg_ 的库导入为例,具体安装以及设置环境变量的教程不在这里赘叙,只讲怎么 Zig 使用已经编译好的 lib。
7171

7272
假如你所处的开发环境系统为 "Windows"、处理器架构为 "x64"、vcpkg 安装目录为 "D:\vcpkg"、并且操作模式为 classic(Classic Mode)、要使用并且已安装的库为 c 运算库 `gsl`
7373

@@ -85,13 +85,13 @@ C 语言共享类型通常是通过引入头文件实现,这点在 zig 中可
8585

8686
::: info 🅿️ 提示
8787

88-
zig 使用 c++ 库的方式同 c 一样,需要保证该库 `extern "C"`,并且在需要使用动态库的时候也同样不能少。
88+
Zig 使用 C++ 库的方式同 C 一样,需要保证该库 `extern "C"`,并且在需要使用动态库的时候也同样不能少。
8989

9090
:::
9191

9292
## `C Translation CLI`
9393

94-
zig 提供了一个命令行工具 `zig translate-c` 供我们使用,它可以将 C 的代码翻译为 zig 的代码,并将其输出到标准输出。
94+
Zig 提供了一个命令行工具 `zig translate-c` 供我们使用,它可以将 C 的代码翻译为 Zig 的代码,并将其输出到标准输出。
9595

9696
### 命令行参数
9797

@@ -213,9 +213,9 @@ zig 支持外部(`extern`)可变参数函数:
213213

214214
### 为什么 zig 可以做到比 c 更好的编译
215215

216-
实际上,zig 本身实现了一个 C 的编译器(目前仅限 linux,其他平台仍使用 llvm),当然不仅仅如此,zig 还提供了一个比较 **_magic_** 的东西—— [`glibc-abi-tool`](https://github.com/ziglang/glibc-abi-tool),这是一个收集每个版本的 glibc 的 `.abilist` 文件的存储库,还包含一个将它们组合成一个数据集的工具。
216+
实际上,Zig 本身实现了一个 C 的编译器(目前仅限 Linux,其他平台仍使用 LLVM),当然不仅仅如此,Zig 还提供了一个比较 **_magic_** 的东西—— [`glibc-abi-tool`](https://github.com/ziglang/glibc-abi-tool),这是一个收集每个版本的 glibc 的 `.abilist` 文件的存储库,还包含一个将它们组合成一个数据集的工具。
217217

218-
所以,zig 本身所谓的“**_ships with libc_**”并不准确,它的确分发 libc,但它只携带每个版本的符号库,仅依赖这个符号库,zig 就可以实现在没有 libc 的情况下仍然正确地进行动态链接!
218+
所以,Zig 本身所谓的“**_ships with libc_**”并不准确,它的确分发 libc,但它只携带每个版本的符号库,仅依赖这个符号库,Zig 就可以实现在没有 libc 的情况下仍然正确地进行动态链接!
219219

220220
::: info 🅿️ 提示
221221

@@ -241,7 +241,7 @@ zig 支持静态链接 musl(针对 linux 的另一个 libc,目标为嵌入
241241
CC='zig cc -target x86_64-linux-gnu' CXX='zig cc -target x86_64-linux-gnu' go build
242242
```
243243

244-
设置 zig 作为 C 编译器来供 go 使用,只要对 ziggo 设置正确的 target,就可以在本机实现完善的交叉编译。
244+
设置 Zig 作为 C 编译器来供 Go 使用,只要对 ZigGo 设置正确的 target,就可以在本机实现完善的交叉编译。
245245

246246
再进一步,我们还可以构建出 linux 的使用 cgo 的静态链接的二进制可执行文件:
247247

course/advanced/memory_manage.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ outline: deep
44

55
# 内存管理
66

7-
> zig 在内存管理方面采取了类似 C 的方案,完全由程序员管理内存,这也是为什么 zig 没有运行时开销的原因,同时这也是为什么 zig 可以在如此多环境(包括实时软件、操作系统内核、嵌入式设备和低延迟服务器)中无缝工作的原因。
7+
> Zig 在内存管理方面采取了类似 C 的方案,完全由程序员管理内存,这也是为什么 Zig 没有运行时开销的原因,同时这也是为什么 Zig 可以在如此多环境(包括实时软件、操作系统内核、嵌入式设备和低延迟服务器)中无缝工作的原因。
88
9-
事实上,在 C 开发中最难以调试的 bug 往往是由于错误的内存管理引起的,zig 在此基础上给我们提供了少量的保护,但仅仅是少量的保护,这就要求程序员在需要明白数据在内存中真实存在的模样(这就涉及到计算机组成原理和操作系统的理论知识了,当然还涉及到一点点的汇编知识)。
9+
事实上,在 C 开发中最难以调试的 bug 往往是由于错误的内存管理引起的,Zig 在此基础上给我们提供了少量的保护,但仅仅是少量的保护,这就要求程序员在需要明白数据在内存中真实存在的模样(这就涉及到计算机组成原理和操作系统的理论知识了,当然还涉及到一点点的汇编知识)。
1010

11-
事实上,zig 本身的标准库为我们提供了多种内存分配模型:
11+
事实上,Zig 本身的标准库为我们提供了多种内存分配模型:
1212

1313
1. [`DebugAllocator`](https://ziglang.org/documentation/master/std/#std.heap.debug_allocator.DebugAllocator)
1414
2. [`SmpAllocator`](https://ziglang.org/documentation/master/std/#std.heap.SmpAllocator)
@@ -20,7 +20,7 @@ outline: deep
2020

2121
除了这八种内存分配模型外,还提供了内存池的功能 [`MemoryPool`](https://ziglang.org/documentation/master/std/#std.heap.memory_pool.MemoryPool)
2222

23-
你可能对上面的多种内存模型感到很迷惑,C 语言中不就是 `malloc` 吗,怎么到这里这么多的“模型”,这些模型均有着不同的特点,而且它们之间有一部分还可以叠加使用,zig 在这方面提供了更多的选择,而且不仅仅是这些,你还可以自己尝试实现一个内存模型。
23+
你可能对上面的多种内存模型感到很迷惑,C 语言中不就是 `malloc` 吗,怎么到这里这么多的“模型”,这些模型均有着不同的特点,而且它们之间有一部分还可以叠加使用,Zig 在这方面提供了更多的选择,而且不仅仅是这些,你还可以自己尝试实现一个内存模型。
2424

2525
:::info 🅿️ 提示
2626

@@ -34,7 +34,7 @@ outline: deep
3434

3535
:::info 🅿️ 提示
3636

37-
补充一点,zig 的内存分配并不会自动进行 0 填充,并且 zig 并没有提供 `calloc` 这种函数,故我们需要手动实现初始化为 0 的操作,不过好在 zig 提供了 [`std.mem.zeroes`](https://ziglang.org/documentation/master/std/#std.mem.zeroes) 函数,用于直接返回某种类型的 0 值。
37+
补充一点,Zig 的内存分配并不会自动进行 0 填充,并且 Zig 并没有提供 `calloc` 这种函数,故我们需要手动实现初始化为 0 的操作,不过好在 Zig 提供了 [`std.mem.zeroes`](https://ziglang.org/documentation/master/std/#std.mem.zeroes) 函数,用于直接返回某种类型的 0 值。
3838

3939
:::
4040

course/basic/advanced_type/opaque.md

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,36 @@ outline: deep
2020

2121
:::
2222

23-
TODO: 添加更多关于该类型使用的示例和说明!
23+
## 常见使用场景
24+
25+
### 与 C 语言互操作
26+
27+
`opaque` 类型最常见的用途是在与 C 代码交互时处理 **不透明指针**(opaque pointer)。当 C 库不公开结构体的内部细节时,Zig 可以使用 `opaque` 类型来安全地表示这些类型:
28+
29+
```zig
30+
// 对应 C 中的 typedef struct FILE FILE;
31+
const FILE = opaque {};
32+
const c = @cImport(@cInclude("stdio.h"));
33+
34+
// 使用不透明指针
35+
fn readFile(file: *FILE) void {
36+
// file 指向一个大小未知的结构体
37+
// 只能通过 C 函数来操作它
38+
_ = file;
39+
}
40+
```
41+
42+
### 类型擦除
43+
44+
使用 `*anyopaque` 可以实现类似 C 语言 `void*` 的类型擦除功能。这在需要存储任意类型指针的场景中很有用:
45+
46+
```zig
47+
const Context = struct {
48+
data: *anyopaque, // 可以指向任意类型
49+
callback: *const fn (*anyopaque) void,
50+
};
51+
```
52+
53+
::: info 🅿️ 提示
54+
使用 `anyopaque` 时需要格外小心类型安全。在可能的情况下,优先考虑使用泛型或联合类型来保持类型信息。
55+
:::

course/basic/define-variable.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ Shadow(遮蔽)指的是在内部作用域中声明一个与外部作用域
126126
::: details 小细节
127127
值得一提的是,Zig 本身并未提供类似 `/* */` 这种多行注释。这意味着多行注释的最佳实践形式是使用多行的 `//`
128128

129-
PS: 说实话,我认为这个设计并不太好
129+
这种设计可能会导致多行注释变得较为冗长
130130
:::
131131

132132
`///` 是文档注释,用于为函数、类型、变量等提供说明。文档注释记录了紧随其后的代码元素。

course/code/15/unit_test.zig

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
pub fn main() !void {}
22

3+
// #region Basic
34
const Basic = struct {
45
const std = @import("std");
56

@@ -22,7 +23,9 @@ const Basic = struct {
2223
return number + 1;
2324
}
2425
};
26+
// #endregion Basic
2527

28+
// #region Nestd
2629
const Nestd = struct {
2730
const std = @import("std");
2831
const expect = std.testing.expect;
@@ -64,11 +67,13 @@ const Nestd = struct {
6467
}
6568
};
6669
};
70+
// #endregion Nestd
6771

6872
test "all" {
6973
_ = Basic;
7074
}
7175

76+
// #region allDecl
7277
const allDecl = struct {
7378
const std = @import("std");
7479
const builtin = @import("builtin");
@@ -80,3 +85,4 @@ const allDecl = struct {
8085
}
8186
}
8287
};
88+
// #endregion allDecl

course/epilogue.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,29 @@ outline: deep
44

55
# 后记
66

7-
TODO
7+
恭喜你完成了 Zig 语言圣经的学习!在这段旅程中,你已经从基础的变量声明、类型系统,一路走到了高级的编译期计算、内存管理和 C 语言交互。相信你现在已经对 Zig 这门语言有了较为全面的理解。
8+
9+
## 学习回顾
10+
11+
通过本教程,你应该已经掌握了:
12+
13+
- **基础概念**:变量声明、基本类型、流程控制、错误处理等核心语法
14+
- **高级类型**:数组、切片、指针、结构体、枚举、联合体等复合类型的使用
15+
- **高级特性**:编译期计算(comptime)、类型反射、原子操作、内存管理等进阶内容
16+
- **工程实践**:构建系统、包管理、单元测试等软件工程知识
17+
- **互操作性**:与 C 语言的无缝交互能力
18+
19+
## 下一步
20+
21+
学习一门语言最好的方式是实践。以下是一些建议的下一步:
22+
23+
1. **阅读官方文档**[Zig 官方文档](https://ziglang.org/documentation/master/) 提供了最权威、最全面的语言参考
24+
2. **阅读标准库源码**:Zig 的标准库代码质量很高,是学习惯用写法的绝佳资源
25+
3. **参与开源项目**:尝试为 Zig 生态中的开源项目贡献代码,在实践中提升
26+
4. **加入社区**:参与 [Zig 中文社区](https://github.com/zigcc) 的讨论,与其他开发者交流学习心得
27+
28+
## 致谢
29+
30+
感谢所有为本教程做出贡献的开发者,感谢 Zig 核心团队和社区成员们对这门语言的持续投入和改进。
31+
32+
如果本教程对你有帮助,欢迎在 [GitHub](https://github.com/zigcc/zig-course) 上给我们一个 Star,也欢迎参与贡献,帮助更多人学习 Zig!

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"type": "module",
33
"scripts": {
4-
"format": "prettier --write . && zig fmt . --exclude zig-out && autocorrect --fix",
4+
"format": "prettier --write . && autocorrect --fix",
55
"dev": "vitepress dev course",
66
"build": "vitepress build course",
77
"preview": "vitepress preview course",

0 commit comments

Comments
 (0)