函数基础 #
一、函数定义 #
1.1 基本函数 #
zig
const std = @import("std");
fn greet() void {
std.debug.print("Hello, Zig!\n", .{});
}
pub fn main() void {
greet();
}
1.2 带参数的函数 #
zig
const std = @import("std");
fn add(a: i32, b: i32) i32 {
return a + b;
}
pub fn main() void {
const result = add(10, 20);
std.debug.print("Result: {}\n", .{result});
}
1.3 多返回值 #
Zig 不支持多返回值,但可以返回元组或结构体:
zig
const std = @import("std");
fn divideAndRemainder(a: i32, b: i32) struct { quotient: i32, remainder: i32 } {
return .{
.quotient = @divTrunc(a, b),
.remainder = @rem(a, b),
};
}
pub fn main() void {
const result = divideAndRemainder(17, 5);
std.debug.print("17 / 5 = {} remainder {}\n", .{ result.quotient, result.remainder });
}
1.4 忽略返回值 #
zig
const std = @import("std");
fn getValue() i32 {
return 42;
}
pub fn main() void {
_ = getValue(); // 忽略返回值
std.debug.print("Ignored return value\n", .{});
}
二、参数 #
2.1 值传递 #
默认情况下,参数是值传递:
zig
const std = @import("std");
fn double(value: i32) i32 {
var v = value;
v *= 2;
return v;
}
pub fn main() void {
const x: i32 = 10;
const result = double(x);
std.debug.print("x = {}, result = {}\n", .{ x, result });
}
2.2 指针传递 #
使用指针可以修改原始值:
zig
const std = @import("std");
fn doubleInPlace(value: *i32) void {
value.* *= 2;
}
pub fn main() void {
var x: i32 = 10;
doubleInPlace(&x);
std.debug.print("x = {}\n", .{x});
}
2.3 切片参数 #
zig
const std = @import("std");
fn sum(numbers: []const i32) i32 {
var total: i32 = 0;
for (numbers) |n| {
total += n;
}
return total;
}
pub fn main() void {
const arr = [_]i32{ 1, 2, 3, 4, 5 };
const result = sum(&arr);
std.debug.print("Sum: {}\n", .{result});
}
2.4 可选参数 #
zig
const std = @import("std");
fn greet(name: ?[]const u8) void {
const actual_name = name orelse "Anonymous";
std.debug.print("Hello, {s}!\n", .{actual_name});
}
pub fn main() void {
greet(null);
greet("Alice");
}
2.5 默认值 #
Zig 不支持函数参数默认值,但可以使用结构体:
zig
const std = @import("std");
const Options = struct {
verbose: bool = false,
timeout: u32 = 30,
retries: u32 = 3,
};
fn connect(host: []const u8, options: Options) void {
std.debug.print("Connecting to {s}\n", .{host});
std.debug.print(" verbose: {}\n", .{options.verbose});
std.debug.print(" timeout: {}\n", .{options.timeout});
std.debug.print(" retries: {}\n", .{options.retries});
}
pub fn main() void {
connect("example.com", .{});
connect("example.com", .{ .verbose = true });
connect("example.com", .{ .timeout = 60, .retries = 5 });
}
三、返回值 #
3.1 基本返回值 #
zig
const std = @import("std");
fn square(x: i32) i32 {
return x * x;
}
pub fn main() void {
std.debug.print("Square of 5: {}\n", .{square(5)});
}
3.2 错误返回 #
zig
const std = @import("std");
fn divide(a: i32, b: i32) !i32 {
if (b == 0) return error.DivisionByZero;
return @divTrunc(a, b);
}
pub fn main() void {
const result = divide(10, 2) catch |err| {
std.debug.print("Error: {}\n", .{err});
return;
};
std.debug.print("Result: {}\n", .{result});
}
3.3 可选返回 #
zig
const std = @import("std");
fn findIndex(arr: []const i32, target: i32) ?usize {
for (arr, 0..) |value, i| {
if (value == target) return i;
}
return null;
}
pub fn main() void {
const arr = [_]i32{ 10, 20, 30, 40, 50 };
if (findIndex(&arr, 30)) |i| {
std.debug.print("Found at index: {}\n", .{i});
} else {
std.debug.print("Not found\n", .{});
}
}
3.4 隐式返回 #
函数末尾的值会隐式返回:
zig
const std = @import("std");
fn max(a: i32, b: i32) i32 {
if (a > b) return a;
b
}
pub fn main() void {
std.debug.print("Max: {}\n", .{max(10, 20)});
}
四、defer #
4.1 基本 defer #
defer 在函数返回前执行:
zig
const std = @import("std");
fn process() void {
std.debug.print("Start\n", .{});
defer std.debug.print("Cleanup\n", .{});
std.debug.print("Processing\n", .{});
}
pub fn main() void {
process();
}
4.2 defer 执行顺序 #
多个 defer 按 LIFO 顺序执行:
zig
const std = @import("std");
fn example() void {
defer std.debug.print("First defer\n", .{});
defer std.debug.print("Second defer\n", .{});
defer std.debug.print("Third defer\n", .{});
std.debug.print("Body\n", .{});
}
pub fn main() void {
example();
}
4.3 defer 用于资源清理 #
zig
const std = @import("std");
fn readFile(path: []const u8) !void {
const file = try std.fs.cwd().openFile(path, .{});
defer file.close();
var buffer: [100]u8 = undefined;
const bytes_read = try file.readAll(&buffer);
std.debug.print("Read {} bytes\n", .{bytes_read});
}
4.4 defer 与作用域 #
zig
const std = @import("std");
pub fn main() void {
std.debug.print("Start\n", .{});
{
defer std.debug.print("Block defer\n", .{});
std.debug.print("Block body\n", .{});
}
std.debug.print("After block\n", .{});
}
五、errdefer #
5.1 基本 errdefer #
errdefer 只在函数返回错误时执行:
zig
const std = @import("std");
fn mightFail(success: bool) !void {
std.debug.print("Start\n", .{});
errdefer std.debug.print("Error cleanup\n", .{});
if (!success) {
return error.Failure;
}
std.debug.print("Success\n", .{});
}
pub fn main() void {
std.debug.print("--- Success case ---\n", .{});
mightFail(true) catch {};
std.debug.print("\n--- Error case ---\n", .{});
mightFail(false) catch {};
}
5.2 资源清理模式 #
zig
const std = @import("std");
fn allocateAndProcess(allocator: std.mem.Allocator, size: usize) ![]u8 {
const buffer = try allocator.alloc(u8, size);
errdefer allocator.free(buffer);
for (buffer, 0..) |*b, i| {
b.* = @intCast(i % 256);
}
return buffer;
}
pub fn main() void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const buffer = allocateAndProcess(allocator, 10) catch |err| {
std.debug.print("Error: {}\n", .{err});
return;
};
defer allocator.free(buffer);
std.debug.print("Buffer: {any}\n", .{buffer});
}
六、函数可见性 #
6.1 pub 函数 #
pub 使函数对外可见:
zig
const std = @import("std");
pub fn publicFunction() void {
std.debug.print("Public function\n", .{});
}
fn privateFunction() void {
std.debug.print("Private function\n", .{});
}
pub fn main() void {
publicFunction();
privateFunction();
}
6.2 文件作用域 #
zig
// utils.zig
pub fn utility() void {
std.debug.print("Utility function\n", .{});
}
fn internal() void {
std.debug.print("Internal function\n", .{});
const std = @import("std");
zig
// main.zig
const std = @import("std");
const utils = @import("utils.zig");
pub fn main() void {
utils.utility();
// utils.internal(); // 错误:不可见
}
七、实战示例 #
7.1 字符串处理函数 #
zig
const std = @import("std");
fn trimWhitespace(str: []const u8) []const u8 {
var start: usize = 0;
var end: usize = str.len;
while (start < end and (str[start] == ' ' or str[start] == '\t')) {
start += 1;
}
while (end > start and (str[end - 1] == ' ' or str[end - 1] == '\t')) {
end -= 1;
}
return str[start..end];
}
pub fn main() void {
const str = " hello world ";
const trimmed = trimWhitespace(str);
std.debug.print("Original: '{s}'\n", .{str});
std.debug.print("Trimmed: '{s}'\n", .{trimmed});
}
7.2 文件处理函数 #
zig
const std = @import("std");
fn readAllFile(path: []const u8, allocator: std.mem.Allocator) ![]u8 {
const file = try std.fs.cwd().openFile(path, .{});
defer file.close();
const stat = try file.stat();
const content = try allocator.alloc(u8, stat.size);
errdefer allocator.free(content);
_ = try file.readAll(content);
return content;
}
pub fn main() void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const content = readAllFile("test.txt", allocator) catch |err| {
std.debug.print("Error: {}\n", .{err});
return;
};
defer allocator.free(content);
std.debug.print("Content: {s}\n", .{content});
}
八、最佳实践 #
8.1 函数命名 #
zig
// 好:动词开头
fn calculateTotal() i32 {}
fn validateInput() bool {}
fn sendEmail() !void {}
// 避免:名词
fn total() i32 {}
fn inputValidation() bool {}
8.2 单一职责 #
zig
// 好:每个函数做一件事
fn validateEmail(email: []const u8) bool {
return std.mem.indexOf(u8, email, "@") != null;
}
fn sendEmail(to: []const u8, subject: []const u8, body: []const u8) !void {
// 发送邮件
}
// 避免:函数做太多事
fn validateAndSendEmail(email: []const u8, subject: []const u8, body: []const u8) !void {
if (std.mem.indexOf(u8, email, "@") == null) return error.InvalidEmail;
// 发送邮件
}
8.3 使用 defer 清理资源 #
zig
// 好
fn processFile(path: []const u8) !void {
const file = try std.fs.cwd().openFile(path, .{});
defer file.close();
// 处理文件
}
// 避免:忘记关闭
fn processFileBad(path: []const u8) !void {
const file = try std.fs.cwd().openFile(path, .{});
// 处理文件
// 忘记关闭文件
}
九、总结 #
函数基础要点:
| 特性 | 说明 |
|---|---|
| fn | 函数定义关键字 |
| pub | 公开可见性 |
| 参数 | 值传递为主 |
| 返回值 | 支持多种类型 |
| defer | 延迟执行 |
| errdefer | 错误时延迟执行 |
下一步,让我们学习泛型函数!
最后更新:2026-03-27