Skip to content

Commit 9a69755

Browse files
committed
docs(course): 添加 Zig 0.16 完整课程代码示例
- 更新构建配置至 0.16 版本 - 添加数组、原子、字符、布尔等基础语言特性示例 - 添加编译期计算、反射、错误处理等高级特性示例 - 添加完整的构建系统示例集(基础、CLI、库、文档等) - 添加包管理和依赖导入示例 - 添加内存管理、网络编程等实战示例
1 parent a401460 commit 9a69755

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+6394
-3
lines changed

build/0.16.zig

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,11 @@ const std = @import("std");
22
const Build = std.Build;
33
const ChildProcess = std.process.Child;
44

5-
const log = std.log.scoped(.For_0_15_0);
5+
const log = std.log.scoped(.For_0_16_0);
6+
const version = "16";
67

78
const args = [_][]const u8{ "zig", "build" };
89

9-
const version = "15";
10-
1110
const relative_path = "course/code/" ++ version;
1211

1312
pub fn build(b: *Build) void {

course/code/16/array.zig

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
pub fn main() !void {
2+
CreateArray.main();
3+
Deconstruct.main();
4+
Matrix.main();
5+
TerminatedArray.main();
6+
Multiply.main();
7+
Connect.main();
8+
FuncInitArray.main();
9+
ComptimeInitArray.main();
10+
}
11+
const CreateArray = struct {
12+
// #region create_array
13+
const print = @import("std").debug.print;
14+
15+
pub fn main() void {
16+
const message = [5]u8{ 'h', 'e', 'l', 'l', 'o' };
17+
// const message = [_]u8{ 'h', 'e', 'l', 'l', 'o' };
18+
print("{s}\n", .{message}); // hello
19+
print("{c}\n", .{message[0]}); // h
20+
}
21+
// #endregion create_array
22+
};
23+
24+
const Deconstruct = struct {
25+
// #region deconstruct
26+
const print = @import("std").debug.print;
27+
28+
fn swizzleRgbaToBgra(rgba: [4]u8) [4]u8 {
29+
// 解构
30+
const r, const g, const b, const a = rgba;
31+
return .{ b, g, r, a };
32+
}
33+
34+
pub fn main() void {
35+
const pos = [_]i32{ 1, 2 };
36+
// 解构
37+
const x, const y = pos;
38+
print("x = {}, y = {}\n", .{ x, y });
39+
40+
const orange: [4]u8 = .{ 255, 165, 0, 255 };
41+
print("{any}\n", .{swizzleRgbaToBgra(orange)});
42+
}
43+
// #endregion deconstruct
44+
};
45+
46+
const Matrix = struct {
47+
// #region matrix
48+
const print = @import("std").debug.print;
49+
50+
pub fn main() void {
51+
const matrix_4x4 = [4][4]f32{
52+
[_]f32{ 1.0, 0.0, 0.0, 0.0 },
53+
[_]f32{ 0.0, 1.0, 0.0, 1.0 },
54+
[_]f32{ 0.0, 0.0, 1.0, 0.0 },
55+
[_]f32{ 0.0, 0.0, 0.0, 1.0 },
56+
};
57+
58+
for (matrix_4x4, 0..) |arr_val, arr_index| {
59+
for (arr_val, 0..) |val, index| {
60+
print("元素{}-{}是: {}\n", .{ arr_index, index, val });
61+
}
62+
}
63+
}
64+
// #endregion matrix
65+
};
66+
67+
const TerminatedArray = struct {
68+
// #region terminated_array
69+
const print = @import("std").debug.print;
70+
71+
pub fn main() void {
72+
const array = [_:0]u8{ 1, 2, 3, 4 };
73+
print("数组长度为: {}\n", .{array.len}); // 4
74+
print("数组最后一个元素值: {}\n", .{array[array.len - 1]}); // 4
75+
print("哨兵值为: {}\n", .{array[array.len]}); // 0
76+
}
77+
// #endregion terminated_array
78+
};
79+
80+
const Multiply = struct {
81+
// #region multiply
82+
const print = @import("std").debug.print;
83+
84+
pub fn main() void {
85+
const small = [3]i8{ 1, 2, 3 };
86+
const big: [9]i8 = small ** 3;
87+
print("{any}\n", .{big}); // [9]i8{ 1, 2, 3, 1, 2, 3, 1, 2, 3 }
88+
}
89+
// #endregion multiply
90+
};
91+
92+
const Connect = struct {
93+
// #region connect
94+
const print = @import("std").debug.print;
95+
96+
pub fn main() void {
97+
const part_one = [_]i32{ 1, 2, 3, 4 };
98+
const part_two = [_]i32{ 5, 6, 7, 8 };
99+
const all_of_it = part_one ++ part_two; // [_]i32{ 1, 2, 3, 4, 5, 6, 7, 8 }
100+
101+
_ = all_of_it;
102+
}
103+
// #endregion connect
104+
};
105+
106+
const FuncInitArray = struct {
107+
// #region func_init_array
108+
const print = @import("std").debug.print;
109+
110+
pub fn main() void {
111+
const array = [_]i32{make(3)} ** 10;
112+
print("{any}\n", .{array});
113+
}
114+
115+
fn make(x: i32) i32 {
116+
return x + 1;
117+
}
118+
// #endregion func_init_array
119+
};
120+
121+
const ComptimeInitArray = struct {
122+
// #region comptime_init_array
123+
const print = @import("std").debug.print;
124+
125+
pub fn main() void {
126+
const fancy_array = init: {
127+
var initial_value: [10]usize = undefined;
128+
for (&initial_value, 0..) |*pt, i| {
129+
pt.* = i;
130+
}
131+
break :init initial_value;
132+
};
133+
print("{any}\n", .{fancy_array});
134+
}
135+
// #endregion comptime_init_array
136+
};

course/code/16/assembly.zig

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
pub fn main() !void {}
2+
3+
const external_assembly = struct {
4+
// #region external_assembly
5+
const std = @import("std");
6+
7+
comptime {
8+
asm (
9+
\\.global my_func;
10+
\\.type my_func, @function;
11+
\\my_func:
12+
\\ lea (%rdi,%rsi,1),%eax
13+
\\ retq
14+
);
15+
}
16+
17+
extern fn my_func(a: i32, b: i32) i32;
18+
19+
pub fn main() void {
20+
std.debug.print("{}\n", .{my_func(2, 5)});
21+
}
22+
// #endregion external_assembly
23+
};
24+
25+
const inline_assembly = struct {
26+
// #region inline_assembly
27+
const std = @import("std");
28+
29+
pub fn main() noreturn {
30+
// Temporarily disabled due to Zig 0.15 syntax changes
31+
// const msg = "hello world\n";
32+
// _ = syscall3(SYS_write, STDOUT_FILENO, @intFromPtr(msg), msg.len);
33+
// _ = syscall1(SYS_exit, 0);
34+
std.process.exit(0);
35+
}
36+
37+
pub const SYS_write = 1;
38+
pub const SYS_exit = 60;
39+
40+
pub const STDOUT_FILENO = 1;
41+
42+
// Temporarily disabled due to Zig 0.15 inline assembly syntax changes
43+
// TODO: Update to new Zig 0.15 inline assembly syntax
44+
45+
// pub fn syscall1(number: usize, arg1: usize) usize {
46+
// var result: usize = undefined;
47+
// asm volatile ("syscall"
48+
// : [ret] "={rax}" (result)
49+
// : [number] "{rax}" (number),
50+
// [arg1] "{rdi}" (arg1)
51+
// : "rcx", "r11"
52+
// );
53+
// return result;
54+
// }
55+
56+
// pub fn syscall3(number: usize, arg1: usize, arg2: usize, arg3: usize) usize {
57+
// var result: usize = undefined;
58+
// asm volatile ("syscall"
59+
// : [ret] "={rax}" (result)
60+
// : [number] "{rax}" (number),
61+
// [arg1] "{rdi}" (arg1),
62+
// [arg2] "{rsi}" (arg2),
63+
// [arg3] "{rdx}" (arg3)
64+
// : "rcx", "r11"
65+
// );
66+
// return result;
67+
// }
68+
// #endregion inline_assembly
69+
};

course/code/16/atomic.zig

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
pub fn main() !void {
2+
// #region atomic_value
3+
const std = @import("std");
4+
const RefCount = struct {
5+
count: std.atomic.Value(usize),
6+
dropFn: *const fn (*RefCount) void,
7+
8+
const RefCount = @This();
9+
10+
fn ref(rc: *RefCount) void {
11+
// no synchronization necessary; just updating a counter.
12+
_ = rc.count.fetchAdd(1, .monotonic);
13+
}
14+
15+
fn unref(rc: *RefCount) void {
16+
// release ensures code before unref() happens-before the
17+
// count is decremented as dropFn could be called by then.
18+
if (rc.count.fetchSub(1, .release) == 1) {
19+
// seeing 1 in the counter means that other unref()s have happened,
20+
// but it doesn't mean that uses before each unref() are visible.
21+
// The load acquires the release-sequence created by previous unref()s
22+
// in order to ensure visibility of uses before dropping.
23+
_ = rc.count.load(.acquire);
24+
(rc.dropFn)(rc);
25+
}
26+
}
27+
28+
fn noop(rc: *RefCount) void {
29+
_ = rc;
30+
}
31+
};
32+
33+
var ref_count: RefCount = .{
34+
.count = std.atomic.Value(usize).init(0),
35+
.dropFn = RefCount.noop,
36+
};
37+
ref_count.ref();
38+
ref_count.unref();
39+
// #endregion atomic_value
40+
41+
}
42+
43+
test "spinLoopHint" {
44+
const std = @import("std");
45+
// #region spinLoopHint
46+
for (0..10) |_| {
47+
std.atomic.spinLoopHint();
48+
}
49+
// #endregion spinLoopHint
50+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
该文件夹是构建系统的示例文件!
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const std = @import("std");
2+
3+
pub fn build(b: *std.Build) void {
4+
const target = b.standardTargetOptions(.{});
5+
const optimize = b.standardOptimizeOption(.{});
6+
7+
const exe = b.addExecutable(.{
8+
.name = "zig",
9+
.root_module = b.createModule(.{
10+
.root_source_file = b.path("src/main.zig"),
11+
.target = target,
12+
.optimize = optimize,
13+
}),
14+
});
15+
16+
b.installArtifact(exe);
17+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
.{
2+
// This is the default name used by packages depending on this one. For
3+
// example, when a user runs `zig fetch --save <url>`, this field is used
4+
// as the key in the `dependencies` table. Although the user can choose a
5+
// different name, most users will stick with this provided value.
6+
//
7+
// It is redundant to include "zig" in this name because it is already
8+
// within the Zig package namespace.
9+
.name = .basic,
10+
11+
// This is a [Semantic Version](https://semver.org/).
12+
// In a future version of Zig it will be used for package deduplication.
13+
.version = "0.0.0",
14+
.fingerprint = 0x907975534fe79435,
15+
16+
// This field is optional.
17+
// This is currently advisory only; Zig does not yet do anything
18+
// with this value.
19+
//.minimum_zig_version = "0.11.0",
20+
21+
// This field is optional.
22+
// Each dependency must either provide a `url` and `hash`, or a `path`.
23+
// `zig build --fetch` can be used to fetch all dependencies of a package, recursively.
24+
// Once all dependencies are fetched, `zig build` no longer requires
25+
// internet connectivity.
26+
.dependencies = .{
27+
// See `zig fetch --save <url>` for a command-line interface for adding dependencies.
28+
//.example = .{
29+
// // When updating this field to a new URL, be sure to delete the corresponding
30+
// // `hash`, otherwise you are communicating that you expect to find the old hash at
31+
// // the new URL.
32+
// .url = "https://example.com/foo.tar.gz",
33+
//
34+
// // This is computed from the file contents of the directory of files that is
35+
// // obtained after fetching `url` and applying the inclusion rules given by
36+
// // `paths`.
37+
// //
38+
// // This field is the source of truth; packages do not come from a `url`; they
39+
// // come from a `hash`. `url` is just one of many possible mirrors for how to
40+
// // obtain a package matching this `hash`.
41+
// //
42+
// // Uses the [multihash](https://multiformats.io/multihash/) format.
43+
// .hash = "...",
44+
//
45+
// // When this is provided, the package is found in a directory relative to the
46+
// // build root. In this case the package's hash is irrelevant and therefore not
47+
// // computed. This field and `url` are mutually exclusive.
48+
// .path = "foo",
49+
50+
// // When this is set to `true`, a package is declared to be lazily
51+
// // fetched. This makes the dependency only get fetched if it is
52+
// // actually used.
53+
// .lazy = false,
54+
//},
55+
},
56+
57+
// Specifies the set of files and directories that are included in this package.
58+
// Only files and directories listed here are included in the `hash` that
59+
// is computed for this package. Only files listed here will remain on disk
60+
// when using the zig package manager. As a rule of thumb, one should list
61+
// files required for compilation plus any license(s).
62+
// Paths are relative to the build root. Use the empty string (`""`) to refer to
63+
// the build root itself.
64+
// A directory listed here means that all files within, recursively, are included.
65+
.paths = .{
66+
"build.zig",
67+
"build.zig.zon",
68+
"src",
69+
// For example...
70+
//"LICENSE",
71+
//"README.md",
72+
},
73+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
const std = @import("std");
2+
3+
pub fn main() !void {
4+
// Prints to stderr (it's a shortcut based on `std.io.getStdErr()`)
5+
std.debug.print("All your {s} are belong to us.\n", .{"codebase"});
6+
7+
// stdout is for the actual output of your application, for example if you
8+
// are implementing gzip, then only the compressed bytes should be sent to
9+
// stdout, not any debugging messages.
10+
var stdout_buffer: [1024]u8 = undefined;
11+
var stdout_writer = std.fs.File.stdout().writer(&stdout_buffer);
12+
const stdout = &stdout_writer.interface;
13+
14+
try stdout.print("Run `zig build test` to run the tests.\n", .{});
15+
16+
try stdout.flush();
17+
}
18+
19+
test "simple test" {
20+
var list = std.ArrayList(i32).init(std.testing.allocator);
21+
defer list.deinit(); // try commenting this out and see if zig detects the memory leak!
22+
try list.append(42);
23+
try std.testing.expectEqual(@as(i32, 42), list.pop());
24+
}

0 commit comments

Comments
 (0)