Базовый синтаксис Zig

Zig — это новый язык программирования, простой и эффективный по дизайну, напрямую совместимый с языком C.

Ниже представлено введение в некоторые основы синтаксиса Zig, которые помогут вам быстро начать.

Расширение файлов с кодом Zig —.zig。


Первая программа на Zig

Давайте сначала посмотрим на программу "Hello, World!" на Zig.

Давайте сначала инициализируем проект zig:

mkdir hello-world
cd hello-world
zig init

Затем создайте файл hello.zig в этом проекте со следующим кодом:

Пример (файл hello.zig)

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();
    try stdout.print("Hello, World!\n", .{});
}

Анализ кода:

1. Импорт стандартной библиотеки:

const std = @import("std");

Эта строка кода импортирует стандартную библиотеку Zig, аналогично в языке C.#include <stdio.h>。

2. Определите функцию main:

pub fn main() !void

pubКлючевое слово указывает, что эта функция является публичной,fnКлючевое слово используется для определения функции,mainявляется точкой входа функции. Тип возвращаемого значения!voidуказывает, что функция не возвращает значение, но может вернуть ошибку (!префикс указывает на тип объединения с ошибкой).

3. Получение стандартного вывода:

const stdout = std.io.getStdOut().writer();

Получите writer стандартного вывода через стандартную библиотеку, затем вызовите его методы для записи содержимого.

4. Напечатайте "Hello, World!":

try stdout.print("Hello, World!\n", .{});

printМетод записывает форматированную строку в стандартный вывод,.{}является пустым списком параметров.tryКлючевое слово передаёт ошибки наверх вызывающему при возникновении ошибки.

Эта программа демонстрирует некоторые базовые возможности языка Zig, такие как определение функций, использование стандартной библиотеки и обработка ошибок.

Если вы просто хотите запустить один файл, можно сразу использовать:

zig run hello.zig

Если вы хотите скомпилировать его в исполняемый файл, используйте:

zig build-exe hello.zig

После компиляции запустите его в терминале:

./hello

Это выведет:

Hello, World!

Идентификаторы

В Zig идентификаторы — это имена, используемые для именования переменных, функций, типов и так далее.

Вот некоторые правила и особенности, касающиеся идентификаторов Zig:

  1. Буквы и цифры: Идентификаторы могут содержать буквы (A-Z и a-z), цифры (0-9) и символы подчеркивания (_).

  2. Начальный символ: Идентификаторы должны начинаться с буквы или символа подчеркивания и не могут начинаться с цифры.

  3. Чувствительность к регистру: Zig — регистрозависимый язык, что означаетVariableиvariable— это два разных идентификатора.

  4. Ключевые и зарезервированные слова: Некоторые конкретные слова зарезервированы в Zig и не могут использоваться в качестве идентификаторов. Например,fn(функция),struct(struct),if(условный оператор) и т. д.

  5. Соглашения об именовании: Zig официально рекомендует следующие соглашения:

    • camelCase: Используется для имён переменных и имён функций. Например,myVariable、calculateSum。
    • PascalCase: Используется для имён типов и пространств имён. Например,Point、ArrayList。
    • SCREAMING_SNAKE_CASE: Используется для констант, известных во время компиляции (comptime-констант). Например,MAX_SIZE。
  6. Опциональный тип: В Zig есть специальный тип?T, который представляет опциональное значение типаT. Это очень полезно при работе со значениями, которые могут быть null.

  7. Константы времени компиляции: Используяcomptimeключевое слово перед идентификатором указывает, что идентификатор является константой времени компиляции.

  8. Типы ошибок: Используяerrorключевое слово определяет типы ошибок, например:

    pub fn openFile(path: []const u8) !void {
        // ...
    }
  9. Суффикс типа: Добавление_tсуффикса после имён типов — это привычка языка C; в Zig можно делать то же самое, но это не обязательно.

Зарезервированные ключевые слова

Ниже приведены некоторые зарезервированные ключевые слова в Zig:

Ключевые словаОписание
alignЗадаёт количество байтов выравнивания для переменной или типа
allowzeroПозволяет указателям указывать на null
andЛогическая операция И
asmБлок встроенного ассемблера
breakВыход из ближайшего цикла или области видимости
callconvСоглашение о вызове
constОпределяет константу
continueПерейти к следующей итерации цикла
deferОтложить выполнение оператора до выхода из области видимости
elseОтрицательная ветвь условного оператора
enumТип перечисления
errdeferОператор отложенного выполнения при возникновении ошибки
errorОпределение типа ошибки
exportЭкспорт символов для использования языком C и т. п.
fnОпределение функции
forЦикл обхода
ifУсловный оператор
inlineВстроенная функция или встроенный цикл
linksectionУказывает секцию компоновщика
noaliasДругие указатели не могут быть псевдонимами этого указателя
noinlineЗапретить встраивание функций
nullЗначение null для опциональных типов
orЛогическая операция ИЛИ
packedУдаляет выравнивание структуры, обеспечивая плотную побитовую упаковку
pubПубличный уровень доступа
returnВозврат из функции
structОпределение типа структуры
switchОператор выбора с несколькими ветвями
testБлок тестового кода
threadlocalПеременная, локальная для потока
tryПопытаться выполнить выражение, распространяя ошибки вверх при сбое
unionОпределение union-типа
usingnamespaceВнести все публичные члены пространства имён в текущую область видимости
varОпределить изменяемую переменную
voidНет типа, часто используется, когда функция не возвращает значение
whileОператор цикла

Базовый синтаксис

1. Переменные и константы

В Zig переменные используютvarключевое слово для определения, константы используютconstключевое слово для определения.

const x: i32 = 10;  // 定义一个整数常量 x,值为 10
var y: f64 = 3.14;  // 定义一个浮点数变量 y,值为 3.14

2. Функции

Функции используютfnключевое слово для определения и указывают возвращаемый тип.

const std = @import("std");

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

pub fn main() !void {
    const result = add(3, 4);
    const stdout = std.io.getStdOut().writer();
    try stdout.print("Result: {}\n", .{result});
}

3. Условные операторы

Используйтеifиelseдля реализации условной логики.

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();
    const number = 10;
    if (number > 0) {
        try stdout.print("Number is positive\n", .{});
    } else {
        try stdout.print("Number is not positive\n", .{});
    }
}

4. Циклы

Zig поддерживаетwhileиforциклах.

const std = @import("std");

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    // while 循环,: (i += 1) 是每次迭代后执行的更新表达式
    var i: i32 = 0;
    while (i < 5) : (i += 1) {
        try stdout.print("i: {}\n", .{i});
    }

    // for 循环,遍历数组
    const array = [5]i32{ 1, 2, 3, 4, 5 };
    for (array) |item| {
        try stdout.print("item: {}\n", .{item});
    }
}

5. Структуры

Zig используетstructдля определения структур.

const std = @import("std");

const Point = struct {
    x: i32,
    y: i32,
};

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();
    const p = Point{ .x = 10, .y = 20 };
    try stdout.print("Point: ({}, {})\n", .{ p.x, p.y });
}

6. Обработка ошибок

Zig использует типы перечислений ошибок иtry / catchключевое слово для обработки ошибок.

const std = @import("std");

const FileError = error{
    FileNotFound,
};

fn readFile(path: []const u8) !void {
    // 模拟一个可能失败的操作
    if (std.mem.eql(u8, path, "invalid")) {
        return FileError.FileNotFound;
    }
    // 其他操作...
}

pub fn main() !void {
    const stdout = std.io.getStdOut().writer();

    readFile("invalid") catch |err| {
        switch (err) {
            FileError.FileNotFound => {
                try stdout.print("Error: File not found\n", .{});
            },
            else => return err,
        }
        return;
    };

    try stdout.print("File read successfully\n", .{});
}

Анализ кода:

  • catch |err|: Перехватить ошибку и привязать её к переменнойerr。
  • switch (err): Сопоставить тип ошибки и обрабатывать разные случаи ошибок отдельно.
  • else => return err: Пробрасывать непредвиденные ошибки напрямую вверх, не игнорируя их молча.
  • ЕслиreadFileвыполняется успешно (без срабатывания catch), затем продолжается выполнение следующего оператора print.
Другие расширения