Skip to content

Your First Zig Program

Now we will write and run a complete Zig program.

Now we will write and run a complete Zig program.

Create a file named:

hello.zig

Put this code inside it:

const std = @import("std");

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

This is a full Zig program. It is small, but it already shows the basic structure used by larger Zig programs.

Running the Program

Open a terminal in the same folder as hello.zig.

Run:

zig run hello.zig

You should see:

Hello, Zig!

The command zig run does two things:

StepMeaning
CompileZig checks your code and turns it into a program
RunZig immediately executes that program

This is useful while learning because you can edit a file, run one command, and see the result.

The Import Line

The first line is:

const std = @import("std");

This loads Zig’s standard library.

The standard library contains common tools: printing, memory utilities, file handling, testing, formatting, data structures, and operating system support.

The name std is just a constant. We could technically choose another name, but Zig programmers almost always use std.

const standard_library = @import("std");

This would work, but it is unusual. Use std.

The Main Function

The next important line is:

pub fn main() void {

The word fn means function.

A function is a named block of code that can run.

The name main is special. In a normal executable program, Zig starts by calling main.

The word pub means public. For main, we write pub so the function is visible as the program entry point.

The word void means the function returns nothing.

So this line means:

Define a public function named main.
It takes no arguments.
It returns nothing.

The body of the function is placed between braces:

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

Everything inside these braces belongs to main.

Printing Text

The line inside main is:

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

This prints text.

The first argument is the format string:

"Hello, Zig!\n"

The \n means newline. It moves the cursor to the next line after printing.

The second argument is:

.{}

This is an empty tuple-like value used for formatting arguments.

For now, read it as:

There are no extra values to insert into the string.

Later, when we print variables, we will put values inside it.

For example:

const age = 10;
std.debug.print("Age: {}\n", .{age});

The {} inside the string is a placeholder. The value age is inserted there.

Changing the Message

Try changing the program:

const std = @import("std");

pub fn main() void {
    std.debug.print("I am learning Zig.\n", .{});
}

Run it again:

zig run hello.zig

You should see:

I am learning Zig.

This is the basic learning loop:

  1. edit the code
  2. run the code
  3. read the output
  4. fix mistakes
  5. run again

You will use this loop constantly.

A Program with a Variable

Now try this version:

const std = @import("std");

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

Output:

Hello, Zig!

This line creates a constant:

const language = "Zig";

A constant is a name for a value that cannot be changed after it is set.

The value is a string:

"Zig"

Then this line prints it:

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

The {s} means “format this value as a string.”

The value language is passed in:

.{language}

So Zig prints:

Hello, Zig!

A Program with a Number

Now try a number:

const std = @import("std");

pub fn main() void {
    const year = 2026;
    std.debug.print("The year is {}.\n", .{year});
}

Output:

The year is 2026.

For numbers, plain {} is enough.

The important idea is that printing uses two parts:

PartExampleMeaning
Format string"The year is {}.\n"Text with placeholders
Arguments.{year}Values inserted into placeholders

The number of placeholders should match the number of arguments.

Common Beginner Mistake: Missing Semicolon

Most Zig statements end with a semicolon.

This is correct:

const year = 2026;

This is wrong:

const year = 2026

If you forget the semicolon, Zig will show a compiler error.

At first, compiler errors may look intimidating. Read them slowly. Zig usually tells you the file, line number, and kind of problem.

Common Beginner Mistake: Wrong Format Placeholder

This is wrong:

const language = "Zig";
std.debug.print("Hello, {}!\n", .{language});

For strings, use {s}:

const language = "Zig";
std.debug.print("Hello, {s}!\n", .{language});

Zig’s formatting is strict. That is useful. It catches mistakes early instead of guessing what you meant.

Building Instead of Running

So far we used:

zig run hello.zig

This compiles and runs immediately.

You can also build an executable:

zig build-exe hello.zig

On Linux and macOS, this creates:

hello

Run it with:

./hello

On Windows, this creates:

hello.exe

Run it with:

.\hello.exe

The difference is:

CommandResult
zig run hello.zigCompile and run now
zig build-exe hello.zigCompile and keep the executable

For small examples, use zig run.

For programs you want to keep, use zig build-exe or later zig build.

What You Have Learned

You have now written a complete Zig program.

You saw how to import the standard library, define main, print text, use a constant, format a string, and run a source file.

This small program is the seed of every larger Zig program. Larger programs have more functions, more files, more types, and more logic, but they still begin with the same basic idea: source code is checked by the compiler, then turned into a program the computer can run.