zig-project

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Zig Project Architecture

Zig项目架构

Core Principles

核心原则

  • No hidden behavior — No hidden allocations, no hidden control flow, no macros
  • Explicit allocators — Pass allocator as parameter, never use global allocator
  • Comptime over macros — Use comptime for generics and metaprogramming
  • Error unions — Use
    !T
    for explicit error handling, avoid
    anyerror
  • defer/errdefer — Resource cleanup at scope exit
  • No backwards compatibility — Delete, don't deprecate. Change directly
  • LiteLLM for LLM APIs — Use LiteLLM proxy for all LLM integrations

  • 无隐藏行为 — 无隐藏内存分配、无隐藏控制流、无宏
  • 显式分配器 — 将分配器作为参数传递,绝不使用全局分配器
  • 用Comptime替代宏 — 使用comptime实现泛型和元编程
  • 错误联合类型 — 使用
    !T
    进行显式错误处理,避免使用
    anyerror
  • defer/errdefer — 在作用域退出时清理资源
  • 无向后兼容性 — 直接删除,不标记废弃。直接修改
  • LLM API使用LiteLLM — 所有LLM集成均使用LiteLLM代理

No Backwards Compatibility

无向后兼容性

Delete unused code. Change directly. No compatibility layers.
zig
// ❌ BAD: Deprecated function kept around
/// Deprecated: Use newFunction instead
pub fn oldFunction() void {
    @compileLog("oldFunction is deprecated");
    newFunction();
}

// ❌ BAD: Alias for renamed functions
pub const old_name = new_name; // "for backwards compatibility"

// ❌ BAD: Unused parameters
fn process(_: *const Config, data: []const u8) !void {
    _ = data;
}

// ✅ GOOD: Just delete and update all usages
pub fn newFunction() void {
    // ...
}

// ✅ GOOD: Remove unused parameters entirely
fn process(data: []const u8) !void {
    // ...
}

删除未使用的代码。直接修改。不保留兼容层。
zig
// ❌ 错误示例:保留已废弃的函数
/// 已废弃:请使用newFunction替代
pub fn oldFunction() void {
    @compileLog("oldFunction is deprecated");
    newFunction();
}

// ❌ 错误示例:为重命名的函数设置别名
pub const old_name = new_name; // "为了向后兼容"

// ❌ 错误示例:保留未使用的参数
fn process(_: *const Config, data: []const u8) !void {
    _ = data;
}

// ✅ 正确示例:直接删除并更新所有调用处
pub fn newFunction() void {
    // ...
}

// ✅ 正确示例:完全移除未使用的参数
fn process(data: []const u8) !void {
    // ...
}

LiteLLM for LLM APIs

LLM API使用LiteLLM

Use LiteLLM proxy. Don't call provider APIs directly.
zig
const std = @import("std");
const http = std.http;

pub const LLMClient = struct {
    allocator: std.mem.Allocator,
    base_url: []const u8,
    api_key: []const u8,

    pub fn init(allocator: std.mem.Allocator, base_url: []const u8, api_key: []const u8) LLMClient {
        return .{
            .allocator = allocator,
            .base_url = base_url,  // "http://localhost:4000"
            .api_key = api_key,
        };
    }

    pub fn complete(self: *LLMClient, prompt: []const u8, model: []const u8) ![]u8 {
        // Use OpenAI-compatible API through LiteLLM proxy
        var client = http.Client{ .allocator = self.allocator };
        defer client.deinit();

        // Build request to LiteLLM proxy...
        _ = prompt;
        _ = model;
        return "";
    }
};

使用LiteLLM代理。不要直接调用服务商API。
zig
const std = @import("std");
const http = std.http;

pub const LLMClient = struct {
    allocator: std.mem.Allocator,
    base_url: []const u8,
    api_key: []const u8,

    pub fn init(allocator: std.mem.Allocator, base_url: []const u8, api_key: []const u8) LLMClient {
        return .{
            .allocator = allocator,
            .base_url = base_url,  // "http://localhost:4000"
            .api_key = api_key,
        };
    }

    pub fn complete(self: *LLMClient, prompt: []const u8, model: []const u8) ![]u8 {
        // 通过LiteLLM代理使用兼容OpenAI的API
        var client = http.Client{ .allocator = self.allocator };
        defer client.deinit();

        // 构建向LiteLLM代理的请求...
        _ = prompt;
        _ = model;
        return "";
    }
};

Quick Start

快速开始

1. Initialize Project

1. 初始化项目

bash
undefined
bash
undefined

Create new project

创建新项目

mkdir myapp && cd myapp zig init
mkdir myapp && cd myapp zig init

Or create executable project

或创建可执行项目

zig init-exe
zig init-exe

Or create library project

或创建库项目

zig init-lib
undefined
zig init-lib
undefined

2. Project Structure

2. 项目结构

myapp/
├── build.zig           # Build configuration (in Zig)
├── build.zig.zon       # Package manifest (dependencies)
├── src/
│   ├── main.zig        # Entry point (for exe)
│   ├── root.zig        # Library root (for lib)
│   └── lib/            # Internal modules
│       └── utils.zig
├── tests/              # Integration tests (optional)
└── lib/                # Vendored dependencies
myapp/
├── build.zig           # Zig编写的构建配置
├── build.zig.zon       # 包清单(依赖管理)
├── src/
│   ├── main.zig        # 可执行项目入口
│   ├── root.zig        # 库项目根文件
│   └── lib/            # 内部模块
│       └── utils.zig
├── tests/              # 集成测试(可选)
└── lib/                # 本地依赖库

3. Core Files

3. 核心文件

build.zig.zon (Package Manifest)
zig
.{
    .name = "myapp",
    .version = "0.1.0",
    .dependencies = .{
        // .some_dep = .{
        //     .url = "https://github.com/...",
        //     .hash = "...",
        // },
    },
    .paths = .{
        "build.zig",
        "build.zig.zon",
        "src",
    },
}
build.zig (Build Script)
zig
const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const exe = b.addExecutable(.{
        .name = "myapp",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    b.installArtifact(exe);

    // Run step
    const run_cmd = b.addRunArtifact(exe);
    run_cmd.step.dependOn(b.getInstallStep());
    const run_step = b.step("run", "Run the application");
    run_step.dependOn(&run_cmd.step);

    // Test step
    const unit_tests = b.addTest(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });
    const run_unit_tests = b.addRunArtifact(unit_tests);
    const test_step = b.step("test", "Run unit tests");
    test_step.dependOn(&run_unit_tests.step);
}

build.zig.zon(包清单)
zig
.{
    .name = "myapp",
    .version = "0.1.0",
    .dependencies = .{
        // .some_dep = .{
        //     .url = "https://github.com/...",
        //     .hash = "...",
        // },
    },
    .paths = .{
        "build.zig",
        "build.zig.zon",
        "src",
    },
}
build.zig(构建脚本)
zig
const std = @import("std");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});

    const exe = b.addExecutable(.{
        .name = "myapp",
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });

    b.installArtifact(exe);

    // 运行步骤
    const run_cmd = b.addRunArtifact(exe);
    run_cmd.step.dependOn(b.getInstallStep());
    const run_step = b.step("run", "Run the application");
    run_step.dependOn(&run_cmd.step);

    // 测试步骤
    const unit_tests = b.addTest(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
    });
    const run_unit_tests = b.addRunArtifact(unit_tests);
    const test_step = b.step("test", "Run unit tests");
    test_step.dependOn(&run_unit_tests.step);
}

Explicit Allocator Pattern

显式分配器模式

Core Principle

核心原则

Every function that allocates must receive an allocator parameter.
zig
const std = @import("std");

// ❌ BAD: Hidden allocation (don't do this)
var global_allocator: std.mem.Allocator = undefined;
fn badAlloc() ![]u8 {
    return global_allocator.alloc(u8, 100);
}

// ✅ GOOD: Explicit allocator
fn goodAlloc(allocator: std.mem.Allocator) ![]u8 {
    return allocator.alloc(u8, 100);
}
每个需要分配内存的函数都必须接收一个分配器参数。
zig
const std = @import("std");

// ❌ 错误示例:隐藏内存分配(请勿这样做)
var global_allocator: std.mem.Allocator = undefined;
fn badAlloc() ![]u8 {
    return global_allocator.alloc(u8, 100);
}

// ✅ 正确示例:显式传递分配器
fn goodAlloc(allocator: std.mem.Allocator) ![]u8 {
    return allocator.alloc(u8, 100);
}

Common Allocators

常用分配器

zig
const std = @import("std");

pub fn main() !void {
    // General purpose (with safety checks in debug)
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    // Arena (bulk alloc/dealloc)
    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    defer arena.deinit();
    const arena_alloc = arena.allocator();

    // Fixed buffer (no heap)
    var buffer: [1024]u8 = undefined;
    var fba = std.heap.FixedBufferAllocator.init(&buffer);
    const fixed_alloc = fba.allocator();

    // Page allocator (direct OS calls)
    const page_alloc = std.heap.page_allocator;

    _ = allocator;
    _ = arena_alloc;
    _ = fixed_alloc;
    _ = page_alloc;
}
zig
const std = @import("std");

pub fn main() !void {
    // 通用分配器(调试模式下包含安全检查)
    var gpa = std.heap.GeneralPurposeAllocator(.{}){};
    defer _ = gpa.deinit();
    const allocator = gpa.allocator();

    // 竞技场分配器(批量分配/释放)
    var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
    defer arena.deinit();
    const arena_alloc = arena.allocator();

    // 固定缓冲区分配器(不使用堆内存)
    var buffer: [1024]u8 = undefined;
    var fba = std.heap.FixedBufferAllocator.init(&buffer);
    const fixed_alloc = fba.allocator();

    // 页分配器(直接调用系统接口)
    const page_alloc = std.heap.page_allocator;

    _ = allocator;
    _ = arena_alloc;
    _ = fixed_alloc;
    _ = page_alloc;
}

Arena Pattern (Request-Scoped)

竞技场模式(请求作用域)

zig
fn handleRequest(permanent_allocator: std.mem.Allocator) !void {
    // Create arena for this request
    var arena = std.heap.ArenaAllocator.init(permanent_allocator);
    defer arena.deinit();  // Free ALL request memory at once

    const allocator = arena.allocator();

    // All allocations use arena - no individual frees needed
    const data = try fetchData(allocator);
    const processed = try processData(allocator, data);
    try sendResponse(processed);

    // arena.deinit() frees everything
}

zig
fn handleRequest(permanent_allocator: std.mem.Allocator) !void {
    // 为当前请求创建竞技场
    var arena = std.heap.ArenaAllocator.init(permanent_allocator);
    defer arena.deinit();  // 一次性释放该请求的所有内存

    const allocator = arena.allocator();

    // 所有分配均使用竞技场 - 无需单独释放
    const data = try fetchData(allocator);
    const processed = try processData(allocator, data);
    try sendResponse(processed);

    // arena.deinit() 会释放所有内存
}

Error Handling

错误处理

Error Unions

错误联合类型

zig
const std = @import("std");

// Define specific error set
const FileError = error{
    NotFound,
    AccessDenied,
    OutOfMemory,
    EndOfStream,
};

// Return error union
fn readFile(allocator: std.mem.Allocator, path: []const u8) FileError![]u8 {
    const file = std.fs.cwd().openFile(path, .{}) catch |err| {
        return switch (err) {
            error.FileNotFound => FileError.NotFound,
            error.AccessDenied => FileError.AccessDenied,
            else => FileError.NotFound,
        };
    };
    defer file.close();

    return file.readToEndAlloc(allocator, 1024 * 1024) catch FileError.OutOfMemory;
}
zig
const std = @import("std");

// 定义特定的错误集合
const FileError = error{
    NotFound,
    AccessDenied,
    OutOfMemory,
    EndOfStream,
};

// 返回错误联合类型
fn readFile(allocator: std.mem.Allocator, path: []const u8) FileError![]u8 {
    const file = std.fs.cwd().openFile(path, .{}) catch |err| {
        return switch (err) {
            error.FileNotFound => FileError.NotFound,
            error.AccessDenied => FileError.AccessDenied,
            else => FileError.NotFound,
        };
    };
    defer file.close();

    return file.readToEndAlloc(allocator, 1024 * 1024) catch FileError.OutOfMemory;
}

try / catch / errdefer

try / catch / errdefer

zig
fn processFile(allocator: std.mem.Allocator, path: []const u8) !void {
    // try: propagate error up
    const data = try readFile(allocator, path);
    errdefer allocator.free(data);  // cleanup on error

    // catch: handle error locally
    const parsed = parseData(data) catch |err| {
        std.log.err("Parse failed: {}", .{err});
        return err;
    };

    try saveResult(parsed);
}
zig
fn processFile(allocator: std.mem.Allocator, path: []const u8) !void {
    // try: 将错误向上传播
    const data = try readFile(allocator, path);
    errdefer allocator.free(data);  // 发生错误时清理资源

    // catch: 本地处理错误
    const parsed = parseData(data) catch |err| {
        std.log.err("解析失败: {}", .{err});
        return err;
    };

    try saveResult(parsed);
}

Error Formatting

错误格式化

zig
fn example() !void {
    doSomething() catch |err| {
        std.log.err("Operation failed: {s}", .{@errorName(err)});
        return err;
    };
}

zig
fn example() !void {
    doSomething() catch |err| {
        std.log.err("操作失败: {s}", .{@errorName(err)});
        return err;
    };
}

Comptime (Compile-Time Execution)

Comptime(编译期执行)

Generic Functions

泛型函数

zig
fn max(comptime T: type, a: T, b: T) T {
    return if (a > b) a else b;
}

// Usage
const result = max(i32, 10, 20);  // Returns 20
const float_result = max(f64, 1.5, 2.5);  // Returns 2.5
zig
fn max(comptime T: type, a: T, b: T) T {
    return if (a > b) a else b;
}

// 使用示例
const result = max(i32, 10, 20);  // 返回20
const float_result = max(f64, 1.5, 2.5);  // 返回2.5

Generic Data Structures

泛型数据结构

zig
pub fn ArrayList(comptime T: type) type {
    return struct {
        const Self = @This();

        items: []T,
        capacity: usize,
        allocator: std.mem.Allocator,

        pub fn init(allocator: std.mem.Allocator) Self {
            return .{
                .items = &[_]T{},
                .capacity = 0,
                .allocator = allocator,
            };
        }

        pub fn deinit(self: *Self) void {
            if (self.capacity > 0) {
                self.allocator.free(self.items.ptr[0..self.capacity]);
            }
        }

        pub fn append(self: *Self, item: T) !void {
            // Implementation...
            _ = item;
        }
    };
}

// Usage
var list = ArrayList(u32).init(allocator);
defer list.deinit();
zig
pub fn ArrayList(comptime T: type) type {
    return struct {
        const Self = @This();

        items: []T,
        capacity: usize,
        allocator: std.mem.Allocator,

        pub fn init(allocator: std.mem.Allocator) Self {
            return .{
                .items = &[_]T{},
                .capacity = 0,
                .allocator = allocator,
            };
        }

        pub fn deinit(self: *Self) void {
            if (self.capacity > 0) {
                self.allocator.free(self.items.ptr[0..self.capacity]);
            }
        }

        pub fn append(self: *Self, item: T) !void {
            // 实现代码...
            _ = item;
        }
    };
}

// 使用示例
var list = ArrayList(u32).init(allocator);
defer list.deinit();

Compile-Time Validation

编译期验证

zig
fn validateConfig(comptime config: Config) void {
    if (config.buffer_size == 0) {
        @compileError("buffer_size must be > 0");
    }
    if (config.buffer_size > 1024 * 1024) {
        @compileError("buffer_size too large");
    }
}

zig
fn validateConfig(comptime config: Config) void {
    if (config.buffer_size == 0) {
        @compileError("buffer_size必须大于0");
    }
    if (config.buffer_size > 1024 * 1024) {
        @compileError("buffer_size过大");
    }
}

Testing

测试

Inline Tests

内联测试

zig
const std = @import("std");
const testing = std.testing;

fn add(a: i32, b: i32) i32 {
    return a + b;
}

test "add positive numbers" {
    try testing.expectEqual(@as(i32, 5), add(2, 3));
}

test "add negative numbers" {
    try testing.expectEqual(@as(i32, -1), add(1, -2));
}
zig
const std = @import("std");
const testing = std.testing;

fn add(a: i32, b: i32) i32 {
    return a + b;
}

test "add positive numbers" {
    try testing.expectEqual(@as(i32, 5), add(2, 3));
}

test "add negative numbers" {
    try testing.expectEqual(@as(i32, -1), add(1, -2));
}

Testing with Allocator

使用分配器的测试

zig
test "allocation test" {
    // Use testing allocator for leak detection
    const allocator = testing.allocator;

    const data = try allocator.alloc(u8, 100);
    defer allocator.free(data);

    try testing.expect(data.len == 100);
}
zig
test "allocation test" {
    // 使用测试分配器检测内存泄漏
    const allocator = testing.allocator;

    const data = try allocator.alloc(u8, 100);
    defer allocator.free(data);

    try testing.expect(data.len == 100);
}

Testing Errors

错误测试

zig
test "expect error" {
    const result = failingFunction();
    try testing.expectError(error.SomeError, result);
}

test "expect no error" {
    const result = try successFunction();
    try testing.expect(result > 0);
}
zig
test "expect error" {
    const result = failingFunction();
    try testing.expectError(error.SomeError, result);
}

test "expect no error" {
    const result = try successFunction();
    try testing.expect(result > 0);
}

Run Tests

运行测试

bash
undefined
bash
undefined

Run all tests

运行所有测试

zig build test
zig build test

Run tests with output

运行测试并显示输出

zig test src/main.zig
zig test src/main.zig

Run specific test

运行指定测试

zig test src/main.zig --test-filter "add positive"

---
zig test src/main.zig --test-filter "add positive"

---

Common Commands

常用命令

bash
undefined
bash
undefined

Build

构建

zig build # Debug build zig build -Doptimize=ReleaseFast # Release build
zig build # 调试版本构建 zig build -Doptimize=ReleaseFast # 发布版本构建

Run

运行

zig build run # Build and run
zig build run # 构建并运行

Test

测试

zig build test # Run tests
zig build test # 运行测试

Format

格式化代码

zig fmt src/ # Format code
zig fmt src/ # 格式化代码

Cross-compile

交叉编译

zig build -Dtarget=x86_64-linux-gnu zig build -Dtarget=aarch64-macos zig build -Dtarget=x86_64-windows
zig build -Dtarget=x86_64-linux-gnu zig build -Dtarget=aarch64-macos zig build -Dtarget=x86_64-windows

Use as C compiler

作为C编译器使用

zig cc -o output input.c zig c++ -o output input.cpp

---
zig cc -o output input.c zig c++ -o output input.cpp

---

Checklist

检查清单

markdown
undefined
markdown
undefined

Project Setup

项目设置

  • build.zig configured
  • build.zig.zon with metadata
  • Source in src/ directory
  • 已配置build.zig
  • 已添加包含元数据的build.zig.zon
  • 源码存放于src/目录

Architecture

架构

  • Explicit allocators everywhere
  • No global state
  • Error sets defined
  • errdefer for cleanup
  • 所有场景均使用显式分配器
  • 无全局状态
  • 已定义错误集合
  • 使用errdefer进行资源清理

Quality

质量

  • Tests with std.testing
  • Memory leak detection in tests
  • zig fmt applied
  • Comptime validation where appropriate
  • 使用std.testing编写测试
  • 测试中启用内存泄漏检测
  • 已使用zig fmt格式化代码
  • 合适的场景下使用编译期验证

Build

构建

  • Debug and Release configs
  • Cross-compilation targets
  • Test step defined

---
  • 已配置调试和发布版本
  • 已配置交叉编译目标
  • 已定义测试步骤

---

See Also

相关链接

  • reference/architecture.md — Project structure patterns
  • reference/tech-stack.md — Libraries and tools
  • reference/patterns.md — Zig idioms and patterns
  • reference/architecture.md — 项目结构模式
  • reference/tech-stack.md — 库和工具
  • reference/patterns.md — Zig惯用写法和模式