Advanced Zig Programming: File I/O, Async Functions, Error Handling, Generics, JSON and Memory Management
76 views
Sure! Below are some more complex Zig code examples that showcase additional language features and more advanced usage.
- File I/O Operations:
const std = @import("std");
pub fn main() !void {
const allocator = std.heap.page_allocator;
// Writing to a file
const file_path = "example.txt";
const file = try std.fs.cwd().createFile(file_path, .{});
defer file.close();
try file.write("Hello, Zig!\n");
// Reading from a file
const read_file = try std.fs.cwd().openFile(file_path, .{});
defer read_file.close();
var buffer: [128]u8 = undefined;
const read_size = try read_file.read(&buffer);
const content = buffer[0..read_size];
const stdout = std.io.getStdOut().writer();
try stdout.print("File Content: {s}\n", .{content});
}
- Concurrency with Asynchronous Functions:
const std = @import("std");
const async = @import("std").async;
pub fn main() void {
const event_loop = async.Loop.instance();
async.run(event_loop, asyncMain);
event_loop.dispatch();
}
fn asyncMain() async void {
const stdout = std.io.getStdOut().writer();
const promise = async.spawn(asyncAddition(5, 7));
const result = await promise;
try stdout.print("Async Result: {}\n", .{result});
}
fn asyncAddition(a: i32, b: i32) async i32 {
// Simulating an asynchronous delay
const delay_duration = std.time.ns_per_ms * 100;
try async.sleep(delay_duration);
return a + b;
}
- Generics and Error Handling:
const std = @import("std");
fn safe_divide(comptime T: type, a: T, b: T) !T {
if (b == 0) {
return error.DivideByZero;
}
return a / b;
}
pub fn main() void {
const stdout = std.io.getStdOut().writer();
const result = safe_divide(i32, 10, 2);
switch (result) {
error.DivideByZero => try stdout.print("Error: Divide by zero.\n", .{}),
else => try stdout.print("Result: {}\n", .{result}),
}
const result2 = safe_divide(i32, 10, 0);
switch (result2) {
error.DivideByZero => try stdout.print("Error: Divide by zero.\n", .{}),
else => try stdout.print("Result: {}\n", .{result2}),
}
}
- JSON Parsing:
const std = @import("std");
pub fn main() !void {
const json_data =
\\{
\\ "name": "Zig",
\\ "version": "0.9.1"
\\}
;
const allocator = std.heap.page_allocator;
const json_tree = try std.json.parse(allocator, json_data);
defer std.json.Value.deinit(json_tree);
const name_field = try json_tree.as.Object.items[name];
const name = try name_field.Value.as.String;
const version_field = try json_tree.as.Object.items[version];
const version = try version_field.Value.as.String;
const stdout = std.io.getStdOut().writer();
try stdout.print("Name: {s}, Version: {s}\n", .{name, version});
}
- Memory Management with Allocators:
const std = @import("std");
pub fn main() void {
const general_purpose_allocator = std.heap.page_allocator;
var data: [][]u8 = undefined;
defer general_purpose_allocator.destroy();
errdefer general_purpose_allocator.freeBytes(data.items);
const input = [5][]u8{ "Alice", "Bob", "Charlie", "Dave", "Eve" };
data = try general_purpose_allocator.alloc([][]u8, 5);
for (input) |e, i| {
data[i] = try general_purpose_allocator.dupe(e);
}
const stdout = std.io.getStdOut().writer();
for (data) |s| {
try stdout.print("User: {s}\n", .{s});
}
}
These more complex examples show how to work with file I/O, asynchronous programming, error handling, generics, JSON parsing, and memory management in Zig. Each example demonstrates the power and flexibility of Zig while keeping in mind its design principles of simplicity and performance.