Introduction to Zig
Welcome to your first lesson in Zig programming! In this introduction, we'll cover what Zig is, why it's unique, and what makes it an excellent choice for systems programming.
What is Zig?
Zig is a general-purpose programming language designed for robustness, optimality, and clarity. Created by Andrew Kelley in 2015, Zig aims to be a better C, providing modern features while maintaining the simplicity and performance that systems programmers need.
What You'll Learn
- What makes Zig different from other programming languages
- Zig's core philosophy and design principles
- How to write your first Zig program
- Why Zig is great for systems programming
Key Features
Simple and Explicit
Zig has no hidden control flow, no hidden memory allocations, and no preprocessor. What you see is what you get:
const std = @import("std");
pub fn main() !void {
// Print to stdout
const stdout = std.io.getStdOut().writer();
try stdout.print("Hello, Zig!\n", .{});
}
Memory Safety Without Garbage Collection
Zig provides memory safety through compile-time checks and clear ownership, without the runtime overhead of a garbage collector:
const std = @import("std");
pub fn main() !void {
// Manual memory management with allocators
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
// Allocate memory
const message = try allocator.alloc(u8, 100);
defer allocator.free(message); // Explicit cleanup
std.debug.print("Memory allocated!\n", .{});
}
Compile-Time Code Execution
One of Zig's most powerful features is comptime - the ability to run code at compile time:
fn fibonacci(comptime n: u32) u32 {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
pub fn main() !void {
// This calculation happens at compile time!
const fib_10 = fibonacci(10);
std.debug.print("10th Fibonacci number: {}\n", .{fib_10});
}
Why Learn Zig?
- Performance: Zero-cost abstractions with C-level performance
- Safety: Catch bugs at compile-time without runtime overhead
- Simplicity: No hidden control flow or allocations
- Interoperability: Seamless C integration without bindings
- Modern Tooling: Built-in build system and package manager
Try It Yourself
Let's write your first Zig program! This example demonstrates basic syntax and output:
const std = @import("std");
pub fn main() !void {
// Variables in Zig
const language = "Zig";
const year: i32 = 2024;
// Print to debug output (easier than stdout for simple examples)
std.debug.print("Learning {s} in {}!\n", .{language, year});
// Basic arithmetic
const a: i32 = 10;
const b: i32 = 20;
std.debug.print("{} + {} = {}\n", .{a, b, a + b});
// Arrays
const numbers = [_]i32{1, 2, 3, 4, 5};
std.debug.print("First number: {}\n", .{numbers[0]});
std.debug.print("Array length: {}\n", .{numbers.len});
}
Try these exercises:
- Change the
languagevariable to your favorite programming language - Add a new variable for your name and print it
- Create a new array with different numbers
- Calculate and print the sum of two numbers
Pro Tip: The best way to learn Zig is by practicing. Try modifying the code examples above and experiment with them in the playground. Don't worry about making mistakes - that's how you learn!
Key Takeaways
- Zig is a modern systems programming language focused on simplicity and safety
- It provides manual memory management without garbage collection overhead
- The
comptimefeature allows code execution at compile time - Zig uses explicit error handling with
!andtrykeywords - No hidden control flow makes code behavior predictable
Next Steps
In the next lesson, we'll dive deeper into variables and Zig's type system, exploring how to declare variables, work with different data types, and understand type inference.
Ready to continue? Let's explore Variables and Types!