Zig Hello World
Writing your first Zig program teaches you the basic structure every Zig file follows. Even a simple "Hello, World!" program reveals how Zig thinks about imports, the main function, and printing to the screen.
The Program
Open your editor and create a file called hello.zig. Type this exactly:
const std = @import("std");
pub fn main() void {
std.debug.print("Hello, World!\n", .{});
}
Save the file. In your terminal, navigate to the folder containing the file and run:
zig run hello.zig
You see Hello, World! printed in the terminal. That is your first Zig program running.
Breaking Down Every Line
Line 1 — Importing the Standard Library
const std = @import("std");
Think of this like unpacking a toolbox. The @import("std") call loads Zig's standard library — a collection of tools for printing, reading files, working with memory, and more. You store all those tools in a constant called std. The @ symbol marks a built-in function that Zig provides. You did not write @import — Zig built it in.
[ Standard Library on disk ]
|
@import("std")
|
v
[ std ] ← Now available in your code
/ \
std.debug std.mem std.fs std.json ...
Line 3 — The Main Function
pub fn main() void {
Every Zig program that runs directly must have a main function. It is the starting point — the first thing that runs when you execute your program. Let us break each word:
- pub — "public," meaning this function is visible to the outside world (the operating system calls
mainto start your program) - fn — short for "function," tells Zig you are defining a function
- main — the name of the function
- () — this function takes no inputs (empty parentheses)
- void — this function returns nothing
pub fn main () void
| | | | |
Public Function Named Accepts Returns
keyword "main" nothing nothing
Line 4 — Printing to the Screen
std.debug.print("Hello, World!\n", .{});
This line calls the print function from the standard library. Think of it as sending a letter — you give it a message template and any values to insert.
std . debug . print ( "Hello, World!\n" , .{} );
| | | | |
The The The The text Values to
lib module function to print insert
(\n = newline) (none here)
The \n inside the string is an escape character that moves the cursor to the next line after printing. Without it, the next terminal output would appear on the same line.
The .{} at the end is an anonymous struct with no fields — Zig's way of saying "no extra values to insert." When you print variables, they go inside this struct.
Printing Variables
You can print variable values inside text using format specifiers. The {} placeholder gets replaced by the value you pass:
const std = @import("std");
pub fn main() void {
const name = "Priya";
const age = 28;
std.debug.print("Name: {s}, Age: {d}\n", .{name, age});
}
Output:
Name: Priya, Age: 28
Format Specifiers
{s} → string
{d} → integer (decimal)
{f} → floating-point number
{} → any type (Zig figures out the format)
{x} → hexadecimal
{b} → binary
Using the correct specifier matters. Passing an integer to {s} causes a compile error. Zig catches this before your program runs.
Using stdout for Full Output Control
std.debug.print works well for quick output and debugging. For programs that write to standard output properly — important when your program's output feeds into another program — use the writer approach:
const std = @import("std");
pub fn main() !void {
const stdout = std.io.getStdOut().writer();
try stdout.print("Hello from stdout!\n", .{});
}
Notice two changes: the return type of main changed to !void (the exclamation mark means "this function can return an error"), and the word try appears before the print call. If printing fails (for example, the terminal closes), try passes the error up to the caller. This is Zig's standard error handling in action.
Compiling Without Running
Sometimes you want to build a program into an executable file and run it later:
zig build-exe hello.zig ./hello
hello.zig
|
zig build-exe
|
v
hello (executable file)
|
./hello
|
v
Hello, World!
zig run compiles and runs in one step. zig build-exe creates the executable file without running it. Both commands produce the same output when you run the program.
Common Beginner Mistakes
Forgetting the Semicolon
Every statement in Zig ends with a semicolon. Leaving one out causes a compile error. The error message tells you exactly which line is missing the semicolon.
Wrong Format Specifier
Passing a number where {s} expects a string causes a compile error. Match the specifier to the type of value you pass.
Missing .{} at the End
The print function always expects two arguments: the format string and the values struct. Even when printing with no variables, pass an empty .{} as the second argument.
Why Zig Chooses This Print API
Other languages use simpler print functions. Python uses print("Hello"). Zig's API looks more complex, but the design ensures every print operation is explicit about what it does. When a function can fail, Zig requires you to acknowledge that possibility. This discipline prevents bugs where a silent failure causes a program to behave incorrectly without any error message.
