Перейти к основному содержимому

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

Разработчику Архитектору Инженеру

Play ITЗагрузка интерактивного демо…


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

Где применяют Zig

Zig позиционируется как замена C — ручная память, компиляция в нативный код, без скрытого runtime. Подходит для системного программирования, когда C++ кажется перегруженным, а Rust — слишком сложным на старте.

zig build и zig run — в одном toolchain; нет отдельного CMake (хотя Zig может собирать C).


Что получится

zig version, файл hello.zig, запуск zig run hello.zig.


Установка Zig

Zig распространяется в виде готовых двоичных сборок для всех основных операционных систем: Windows, macOS и Linux. Установка не требует сложных зависимостей и занимает несколько минут.


На Windows

  1. Перейдите на официальный сайт Zig: https://ziglang.org/download/
  2. В разделе Windows скачайте архив с последней стабильной версией (обычно файл с расширением .zip).
  3. Распакуйте архив в удобное место, например, в папку C:\zig.
  4. Добавьте путь к папке zig в переменную окружения PATH. Это позволит запускать команду zig из любого места в терминале.
    • Нажмите Win + R, введите sysdm.cpl, откройте вкладку Дополнительно, затем нажмите Переменные среды.
    • В разделе Системные переменные найдите Path, нажмите Изменить, затем Создать и укажите путь, например: C:\zig.
  5. Проверка в новом окне PowerShell или cmd:
zig version

Ожидаемый вывод, например 0.13.0 или 0.14.0.

Версия примеров: фрагменты кода в разделе ориентированы на Zig 0.12+ (build system, @memcpy, Autodoc). При обновлении компилятора сверяйтесь с release notes.


На macOS

Через Homebrew:

brew install zig

Если вы предпочитаете установку вручную:

  1. Скачайте архив для macOS с официального сайта.
  2. Распакуйте его, например, в папку ~/Applications/zig.
  3. Добавьте путь в PATH. Для этого откройте файл ~/.zshrc (или ~/.bashrc, если используется bash) и добавьте строку:
export PATH="$PATH:$HOME/Applications/zig"
  1. Перезагрузка настроек оболочки:
source ~/.zshrc
  1. Проверка:
zig version

На Linux

Для большинства дистрибутивов рекомендуется использовать официальные сборки с сайта, так как версии в репозиториях часто устаревают.

  1. Скачайте архив, соответствующий вашей архитектуре (обычно x86_64-linux).
  2. Распакуйте его, например, в /opt/zig:
sudo tar -xzf zig-linux-x86_64-*.tar.xz -C /opt
sudo mv /opt/zig-linux-x86_64-* /opt/zig
  1. Добавьте путь в PATH. Откройте ~/.bashrc или ~/.profile и добавьте:
export PATH="$PATH:/opt/zig"
  1. Примените изменения:
source ~/.bashrc
  1. Проверьте установку:
zig version

Выбор среды разработки

Zig не требует специальной интегрированной среды разработки (IDE). Достаточно любого текстового редактора с поддержкой синтаксиса Zig. Однако для удобства можно использовать следующие варианты:

  • Visual Studio Code — самый популярный выбор. Установите расширение Zig Language Support от автора tiehuis. Оно предоставляет подсветку синтаксиса, автодополнение, навигацию по коду и интеграцию с компилятором.
  • Vim / Neovim — с плагином zig.vim или через LSP-клиент (например, nvim-lspconfig с сервером zls).
  • Emacs — с пакетом zig-mode.
  • JetBrains Rider или CLion — поддерживают Zig через плагины, но требуют дополнительной настройки.

Для первой программы подойдёт даже Блокнот, но использование редактора с подсветкой синтаксиса значительно упрощает чтение и отладку кода.


Создание первой программы

В терминале:

mkdir hello-zig
cd hello-zig

Внутри этой папки создайте файл с именем main.zig. Имя файла может быть любым, но по соглашению точка входа в программу часто называется main.zig.

Откройте файл в выбранном редакторе и введите следующий код:

const std = @import("std");

pub fn main() void {
std.debug.print("Hello, World!\n", .{});
}

Разбор:

  • const std = @import("std"); подключает стандартную библиотеку Zig и сохраняет модуль в неизменяемую константу std.
  • pub fn main() void объявляет публичную точку входа программы; void показывает, что функция не возвращает значение.
  • std.debug.print("Hello, World!\n", .{}); печатает строку в консоль; \n переводит курсор на новую строку.
  • Второй аргумент .{} — пустой кортеж параметров форматирования, потому что в строке нет шаблонов вроде {s} или {d}.

Разберём каждую строку подробно.


Строка 1 — импорт стандартной библиотеки

const std = @import("std");

Разбор:

  • @import("std") — встроенная функция компилятора, которая подгружает модуль стандартной библиотеки.
  • const запрещает переназначение переменной: модуль std нельзя случайно перезаписать.
  • Такое объявление обычно ставят в начале файла, чтобы далее обращаться к API через пространства имён (std.debug, std.mem, std.fs).

Ключевое слово const объявляет неизменяемую переменную. Здесь переменной std присваивается результат вызова встроенной функции @import("std"). Эта функция загружает модуль стандартной библиотеки Zig, которая содержит базовые инструменты — работу с памятью, вводом-выводом, строками, потоками и многое другое. Стандартная библиотека в Zig — это часть самого языка, встроенная в компилятор.


Строка 3 — определение функции main

pub fn main() void {

Разбор:

  • pub делает функцию видимой извне текущего файла/модуля, чтобы рантайм мог вызвать её как точку входа.
  • fn — ключевое слово объявления функции.
  • main — специальное имя стартовой функции исполняемой программы.
  • () означает, что функция не принимает аргументы напрямую; аргументы CLI в Zig читают через std.process.

Функция main — это точка входа в программу. Ключевое слово pub означает, что функция видна за пределами текущего модуля (это необходимо, чтобы система запуска могла её вызвать). Слово fn объявляет функцию. После имени main в скобках указываются параметры — в данном случае их нет. Тип возврата указан как void, что означает: функция ничего не возвращает.


Строка 4 — вывод текста

std.debug.print("Hello, World!\n", .{});

Разбор:

  • std.debug.print использует форматируемый вывод в стиле стандартной библиотеки Zig.
  • Строка "Hello, World!\n" содержит escape-последовательность \n, поэтому следующий вывод начнётся с новой строки.
  • .{} — литерал tuple с аргументами для форматтера; он пустой, потому что плейсхолдеров нет.
  • Если бы в строке был шаблон {s}, сюда передавали бы соответствующее значение, например .{name}.

Вызов std.debug.print отправляет текст в стандартный поток вывода (обычно консоль). Первый аргумент — строковый литерал "Hello, World!\n". Символ \n в конце обеспечивает переход на новую строку после вывода. Второй аргумент — это кортеж (tuple), обозначенный как .{}. В Zig форматирование строки выполняется через заполнители, такие как {}. В данном случае строка не содержит заполнителей, поэтому передаётся пустой кортеж.

Важно: std.debug.print предназначен для отладки и работает даже в режимах, где другие функции ввода-вывода могут быть отключены. Для полноценного вывода в конечных приложениях рекомендуется использовать std.io.getStdOut().writer().


Компиляция и запуск

Из каталога hello-zig:

zig run main.zig

Разбор:

  • zig run компилирует main.zig во временный исполняемый файл и сразу запускает его.
  • Отдельный шаг zig build-exe не нужен для быстрой проверки примера.
  • Ошибки компиляции и линковки выводятся в терминал до запуска программы.

Команда zig run компилирует файл и сразу запускает полученный исполняемый файл. В консоли появится:

Hello, World!

Это означает, что программа успешно выполнена.

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

zig build-exe main.zig

На выходе будет создан файл main (в Linux/macOS) или main.exe (в Windows). Его можно запустить напрямую:

./main # Linux/macOS
main.exe # Windows

По умолчанию Zig компилирует в режиме отладки (Debug), который включает проверки границ массивов, переполнения и другие средства безопасности. Для выпуска производственной версии используйте флаг:

zig build-exe -O ReleaseFast main.zig

Флаг -O ReleaseFast отключает часть отладочных проверок и включает оптимизации. Для баланса безопасности и скорости есть -O ReleaseSafe.


Следующий шаг — проект с build.zig

После hello world удобно создать каркас проекта:

zig init

Разбор:

  • Команда создаёт каркас проекта с системой сборки Zig.
  • Появляются build.zig (скрипт сборки), build.zig.zon (манифест зависимостей) и src/main.zig.
  • Дальше проект собирают через zig build, а не только однофайловым zig run.

Появятся build.zig, build.zig.zon и src/main.zig. Сборка и запуск:

zig build
zig build run

Тесты: zig build test. Документация: zig build doc (если цель добавлена в build.zig).


Частые ошибки

СимптомПричина
zig: command not foundНе добавлен в PATH после распаковки
Ошибка линковки на WindowsНужен LLVM/линкер — установите Build Tools
error: file not foundЗапуск не из каталога с main.zig

Что попробовать

Сниппет с подстановкой имени в строку:

const std = @import("std");

pub fn main() void {
const name = "Zig";
std.debug.print("Hello, {s}!\n", .{name});
}

Разбор:

  • {s} — плейсхолдер для строки ([]const u8 или совместимого типа).
  • Второй аргумент . {name} — tuple значений для форматтера; порядок должен совпадать с плейсхолдерами.
  • name можно заменить на args[1] из упражнения с CLI ниже.

Минимальный тест в том же main.zig:

const std = @import("std");

test "smoke" {
try std.testing.expect(true);
}

Разбор:

  • Блок test "smoke" компилируется только при zig test main.zig.
  • expect(true) проверяет условие; при ложном значении тест падает с ошибкой.
  • Так можно быстро убедиться, что toolchain и проект настроены корректно.
  1. zig test main.zig — добавьте блок test в файл и запустите тест.
  2. Замените строку вывода на std.debug.print("Hello, {s}!\n", .{"Zig"}); и проверьте форматтер.
  3. Соберите бинарник в двух режимах: -O Debug и -O ReleaseSafe, затем сравните поведение на ошибках.
  4. Сравните с C и зафиксируйте, где Zig снимает типичные риски C.

Мини-упражнение — аргументы командной строки

Добавьте в main.zig чтение аргументов. Программа должна печатать приветствие с именем, если имя передано:

Код ITЗагрузка примера кода…

Разбор:

  • Сигнатура pub fn main() !void означает, что функция может завершиться ошибкой; !void — error union.
  • GeneralPurposeAllocator создаёт универсальный аллокатор, а defer _ = gpa.deinit(); гарантирует корректное освобождение ресурсов при выходе.
  • std.process.argsAlloc(allocator) копирует аргументы командной строки в память, выделенную этим аллокатором; argsFree освобождает её симметрично.
  • Проверка if (args.len < 2) валидирует, что пользователь передал имя, иначе печатается инструкция запуска.
  • args[1] — первый пользовательский аргумент (элемент args[0] обычно содержит имя программы), который подставляется в {s} как UTF-8 срез.

Запуск:

zig run main.zig -- Tim

Куда идти дальше


В подборках

Статья входит в тематические подборки и блок "С чего начать?" на главной. Соседние шаги того же маршрута:

Первые шаги (маршрут подборки) — Первая программа на Elixir, Первая программа на Nim, Первая программа на Scala, Первая программа на Dart, Первая программа на Haskell, Первая программа на R.