← Certified Zig Programming Expert · Lesson 3 of 5

Module Two

📖 Every lesson in this course is free to read right here, no account needed. Create a free account to track your progress, take the exam, and earn your certificate.
1

Course Outline

Certified Zig Programming Expert · Course Outline
⚡ certification · 2026

Certified Zig Programming Expert

⚡ systems programming · comptime · memory safety 🧠 4 weeks · hands-on
🎯 level Beginner to intermediate · programmers
⏳ duration 4 weeks · 6–8 hours / week
🛠️ tools Zig 0.13+ · Zig Build System · Zig CC · VS Code · LLDB
Week 1 Zig Foundations & Core Syntax
Learn what makes Zig special, set up your environment, and master the core language features.
  • Why Zig? Safety, speed & simplicity
  • Installing Zig & setting up your editor
  • Variables, constants & primitive types
  • Control flow: if, while, for, switch
  • Functions, structs, enums & unions
  • Slices, arrays & strings
✓ outcome Write, compile, and run basic Zig programs with confidence
Week 2 Memory Management & Error Handling
Master Zig's explicit memory model, allocators, optionals, and error unions.
  • Pointers & memory layout
  • Allocators (GeneralPurposeAllocator, ArenaAllocator)
  • Manual memory management & defer/errdefer
  • Optionals (?T) & error unions (!T)
  • try, catch & error handling patterns
  • Comptime basics & generics
✓ outcome Write memory-safe Zig code with proper error handling and allocators
Week 3 Advanced Features & Standard Library
Dive into comptime, the Zig Build System, testing, and the standard library.
  • Advanced comptime metaprogramming
  • Generics & compile-time reflection
  • Zig Build System (build.zig)
  • Unit testing & test blocks
  • Zig Standard Library tour
  • Interfacing with C (C ABI, @cImport)
✓ outcome Build multi-file Zig projects with tests and C interop
Week 4 Real-World Projects & Certification
Apply everything you have learned to build real systems and earn your certification.
  • Concurrency with threads & async patterns
  • Networking & sockets in Zig
  • Cross-compilation & Zig CC
  • Performance optimization & benchmarking
  • Packaging & publishing Zig libraries
  • Certification project & exam preparation
✓ outcome Complete a full Zig project and pass the certification exam

⚡ certification project expert

"Zig Systems Project" — design and implement a complete systems-level application in Zig (e.g., a CLI tool, HTTP server, or memory-efficient data processor). Include proper memory management, error handling, tests, and documentation.

🎯 portfolio piece · peer review · certification exam


⚡ includes hands-on labs, real-world projects, and certification exam preparation.
2

Module One

Certified Zig Programming Expert – Module One

Module One: Zig Foundations and Core Syntax – Your First Steps into Zig

“Certified Zig Programming Expert” – Master the language of modern systems programming

Module Introduction

Welcome, young programmer! Have you ever wondered how computer programs are made? Programs are written in special languages called programming languages. There are many languages, like Python, JavaScript, and C. Today, we are going to learn a very special language called Zig.

Zig is a modern programming language that is simple, fast, and safe. It is used to build operating systems, games, servers, and many other important programs. Zig was created to fix problems in older languages like C. It gives you control over your computer while keeping you safe from common mistakes.

In this module, we will start from the very beginning. You don't need any experience with programming. We will learn what Zig is, how to set it up, and how to write your first programs. We will learn about variables, data types, control flow, functions, structs, and more. By the end of this module, you will be able to write simple Zig programs with confidence.

Let's begin!

Learning Objectives

After finishing this module, you will be able to:

  • Explain what Zig is and why it is special.
  • Install Zig and set up your coding environment.
  • Write and run your first Zig program.
  • Use variables and constants.
  • Understand Zig's primitive data types.
  • Use control flow statements: if, while, for, switch.
  • Write and call functions.
  • Create and use structs and enums.
  • Work with arrays, slices, and strings.
  • Complete a mini project and practical assignment.

Warm-up Story: Chidi’s First Program

Chidi is 13 years old and lives in Lagos. He loves computers and wants to learn how to make his own programs. One day, his uncle, who is a software engineer, told him about a new language called Zig.

“Zig is amazing,” his uncle said. “It is simple, fast, and safe. It lets you build things that are very close to the computer's heart.” Chidi was curious. “Can I learn it?” he asked. “Of course!” his uncle replied. “Let's start today.”

Chidi’s uncle helped him install Zig on his computer. They opened a code editor and wrote a simple program. It printed the words “Hello, Zig!” on the screen. Chidi was so happy. He had written his first program!

Next, they learned about variables. Chidi created a variable called “name” and put his name in it. He created another variable called “age” and put his age in it. Then they learned about functions, structs, and arrays. Every new idea was like a new toy to play with.

By the end of the day, Chidi had written five small programs. He felt like a real programmer. “Zig is fun!” he said. His uncle smiled. “This is just the beginning. Keep learning, and you will build amazing things.”

Moral of the story: Programming is like learning a new language. Zig is a simple, powerful language that anyone can learn. Start with small steps, and you will go far.

Main Lessons

Lesson 1: What is Zig?

Definition: Zig is a modern programming language used to build fast, safe, and reliable software.

Why it is important: Zig is designed to fix problems in older languages and make programming simpler.

Simple explanation: Imagine you have a toolbox. Some tools are old and rusty. Zig is a new, shiny tool that works better.

Real-life example: Companies use Zig to build operating systems, web servers, and games.

School example: A student uses Zig to build a simple calculator program.

Home example: A family uses a Zig program to organize their shopping list.

Nigerian example: A Nigerian startup uses Zig to build a fast payment system.

Illustration:

  Zig = Modern Programming Language
        |
        V
  Simple, Fast, Safe
        |
        V
  Used for:
  - Operating systems
  - Web servers
  - Games
  - Tools
  

Mini summary: Zig is a modern programming language. It is simple, fast, and safe. It is used to build many kinds of software.

Lesson 2: Why Learn Zig?

Definition: Learning Zig means you can build powerful programs that run very fast.

Why it is important: Zig gives you control and safety at the same time.

Simple explanation: Imagine driving a car that is both fast and safe. That is Zig.

Real-life example: Game developers use Zig for high-performance games.

School example: Students learn Zig to understand how computers really work.

Home example: Hobbyists use Zig to build small tools and games.

Nigerian example: Nigerian developers use Zig for efficient software.

Illustration:

  Why Learn Zig?
  +---------------------+
  | Fast                |
  +---------------------+
  | Safe                |
  +---------------------+
  | Simple              |
  +---------------------+
  | Powerful            |
  +---------------------+
  | Modern              |
  +---------------------+
  

Mini summary: Zig is fast, safe, simple, and powerful. It is a great language to learn.

Lesson 3: Installing Zig

Definition: Installing Zig means putting the Zig compiler on your computer.

Why it is important: You need the compiler to turn your code into a program.

Simple explanation: Like installing a new app on your phone before you can use it.

Real-life example: Developers install Zig to build software.

School example: Students install Zig on school computers.

Home example: Families install Zig on home computers.

Nigerian example: Nigerian developers install Zig to build tools.

Illustration:

  Installing Zig:
  1. Go to ziglang.org
  2. Download the version for your computer
  3. Extract the file
  4. Add Zig to your PATH
  5. Open a terminal and type: zig version
  6. You should see the version number 🎉
  

Step-by-step:

  1. Visit the official Zig website (ziglang.org).
  2. Download the version for your operating system.
  3. Extract the downloaded file to a folder.
  4. Add that folder to your system PATH.
  5. Open a terminal and type zig version.
  6. If you see a version number, Zig is installed!

Mini summary: Install Zig by downloading it and adding it to your PATH. Check with zig version.

Lesson 4: Your First Zig Program

Definition: A Zig program is a set of instructions that tells the computer what to do.

Why it is important: Writing your first program is the start of your journey.

Simple explanation: Like writing your first sentence in a new language.

Real-life example: Programmers start with “Hello, World!”

School example: Students write “Hello, World!” in class.

Home example: Families write simple programs for fun.

Nigerian example: Nigerian students write “Hello, Nigeria!”

Illustration:

  hello.zig:

  const std = @import("std");

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

  Run it:
  zig run hello.zig

  Output:
  Hello, Zig!
  

Step-by-step:

  1. Create a file called hello.zig.
  2. Type the code above.
  3. Open a terminal.
  4. Type zig run hello.zig.
  5. See the output “Hello, Zig!”

Mini summary: Your first Zig program prints “Hello, Zig!” to the screen. Run it with zig run.

Lesson 5: Variables and Constants

Definition: A variable is a box that holds a value that can change. A constant holds a value that cannot change.

Why it is important: Variables and constants let you store and use data.

Simple explanation: Imagine a labeled box. You can put things in and take them out (variable). A sealed box cannot be changed (constant).

Real-life example: A bank stores your balance in a variable.

School example: A teacher stores a student's score in a variable.

Home example: A family stores the number of eggs in a variable.

Nigerian example: A trader stores the price of rice in a variable.

Illustration:

  Variables and Constants:

  var age: u8 = 13;       // can change
  const pi: f32 = 3.14;   // cannot change

  age = 14;  // OK
  pi = 3.15; // ERROR
  

Step-by-step:

  1. Use var to create a variable.
  2. Use const to create a constant.
  3. Give a type (like u8 for small numbers).
  4. Give a name.
  5. Assign a value with =.

Mini summary: Variables can change; constants cannot. Use var and const.

Lesson 6: Primitive Data Types

Definition: Data types describe what kind of value a variable holds: numbers, text, true/false, etc.

Why it is important: Knowing data types helps you store data correctly.

Simple explanation: Like different containers for different things: bottles for water, boxes for books.

Real-life example: Banks use numbers for money and text for names.

School example: Teachers use numbers for scores and text for names.

Home example: Families use numbers for ages and text for addresses.

Nigerian example: Businesses use numbers for prices and text for product names.

Illustration:

  Common Zig Types:
  +----------+---------------------------+
  | Type     | What It Holds             |
  +----------+---------------------------+
  | u8       | Small positive number     |
  | i32      | Whole number (positive/neg)|
  | f64      | Decimal number            |
  | bool     | true or false             |
  | []u8     | Text (string)             |
  +----------+---------------------------+
  

Mini summary: Zig has many data types: numbers (u8, i32, f64), booleans (bool), and text ([]u8).

Lesson 7: Control Flow – if and switch

Definition: Control flow lets your program make decisions.

Why it is important: Decisions make programs smart.

Simple explanation: Like choosing what to wear based on the weather.

Real-life example: A bank checks if you have enough money before you withdraw.

School example: A teacher gives a pass or fail based on a score.

Home example: A family decides to buy food based on the budget.

Nigerian example: A trader decides to sell based on the price.

Illustration:

  if statement:

  const score: u8 = 85;
  if (score >= 70) {
      std.debug.print("Pass!\n", .{});
  } else {
      std.debug.print("Fail.\n", .{});
  }

  switch statement:

  const day: u8 = 3;
  switch (day) {
      1 => std.debug.print("Monday\n", .{}),
      2 => std.debug.print("Tuesday\n", .{}),
      3 => std.debug.print("Wednesday\n", .{}),
      else => std.debug.print("Other day\n", .{}),
  }
  

Step-by-step:

  1. Use if to test a condition.
  2. Use else for the other case.
  3. Use switch to choose between many options.
  4. Test your program with different values.

Mini summary: Use if and switch to make decisions in your program.

Lesson 8: Control Flow – while and for

Definition: Loops let you repeat a block of code many times.

Why it is important: Loops save time and let you process lists.

Simple explanation: Like doing push-ups 10 times in a row.

Real-life example: A bank processes many transactions in a loop.

School example: A teacher adds up the scores of all students.

Home example: A family counts all items in a shopping list.

Nigerian example: A trader calculates total sales for the day.

Illustration:

  while loop:

  var i: u8 = 1;
  while (i <= 5) : (i += 1) {
      std.debug.print("{d}\n", .{i});
  }

  for loop:

  const numbers = [_]u8{10, 20, 30};
  for (numbers) |n| {
      std.debug.print("{d}\n", .{n});
  }
  

Step-by-step:

  1. Use while to repeat while a condition is true.
  2. Use for to go through a list of items.
  3. Make sure your loop ends.
  4. Test with small numbers first.

Mini summary: Use while and for to repeat code. Loops are powerful tools.

Lesson 9: Functions

Definition: A function is a block of code that does a specific job and can be reused.

Why it is important: Functions make programs cleaner and easier to reuse.

Simple explanation: Like a recipe you can use again and again.

Real-life example: A bank uses a function to calculate interest.

School example: A teacher uses a function to calculate averages.

Home example: A family uses a function to calculate budget totals.

Nigerian example: A trader uses a function to calculate prices.

Illustration:

  Function Example:

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

  pub fn main() void {
      const result = add(3, 4);
      std.debug.print("Sum: {d}\n", .{result});
  }
  

Step-by-step:

  1. Use fn to start a function.
  2. Give the function a name.
  3. List its inputs (parameters).
  4. Write its return type.
  5. Write the body with return.

Mini summary: Functions are reusable blocks of code. Use fn to define them and call them by name.

Lesson 10: Structs and Enums

Definition: A struct groups related data together. An enum is a list of named values.

Why it is important: They help you organize your data clearly.

Simple explanation: A struct is like a bag with labeled pockets. An enum is like a list of choices on a menu.

Real-life example: A bank uses structs for customer info and enums for account types.

School example: A teacher uses structs for student info and enums for grades.

Home example: A family uses structs for family members and enums for roles.

Nigerian example: A trader uses structs for products and enums for categories.

Illustration:

  Struct and Enum:

  const Color = enum { red, green, blue };

  const Person = struct {
      name: []const u8,
      age: u8,
      favorite: Color,
  };

  const ada = Person{
      .name = "Ada",
      .age = 13,
      .favorite = .green,
  };
  

Step-by-step:

  1. Use struct to group related data.
  2. Use enum to list named values.
  3. Create instances and set fields.
  4. Access fields with dots: ada.name.

Mini summary: Structs group data; enums list named values. They make your code organized and clear.

Lesson 11: Arrays and Slices

Definition: An array is a fixed-size list. A slice is a view into a part of an array.

Why it is important: Arrays and slices let you work with many values at once.

Simple explanation: An array is like a row of boxes. A slice points to some of those boxes.

Real-life example: A bank uses an array for transaction history.

School example: A teacher uses an array for class scores.

Home example: A family uses an array for shopping items.

Nigerian example: A trader uses an array for daily sales.

Illustration:

  Array and Slice:

  const numbers = [_]u8{1, 2, 3, 4, 5};  // array
  const part = numbers[1..4];            // slice

  for (part) |n| {
      std.debug.print("{d}\n", .{n});
  }
  

Step-by-step:

  1. Create an array with [_]type{values}.
  2. Create a slice with array[start..end].
  3. Use for to loop through them.

Mini summary: Arrays hold fixed lists; slices point to parts of lists. Both are used with loops.

Lesson 12: Strings in Zig

Definition: A string is a list of characters. In Zig, strings are slices of bytes: []const u8.

Why it is important: Strings let you work with text.

Simple explanation: Like writing a sentence using letters.

Real-life example: Banks store customer names as strings.

School example: Teachers store student names as strings.

Home example: Families store addresses as strings.

Nigerian example: Businesses store product names as strings.

Illustration:

  String Example:

  const name: []const u8 = "Ada";
  std.debug.print("Hello, {s}!\n", .{name});

  Output:
  Hello, Ada!
  

Step-by-step:

  1. Create a string with const name = "text";.
  2. Use {s} in print to show it.
  3. You can slice strings like arrays.

Mini summary: Strings are slices of bytes. Use {s} to print them.

Lesson 13: Compiling and Running Zig Programs

Definition: Compiling means turning your code into a program the computer can run.

Why it is important: You need to compile before you can run your program.

Simple explanation: Like baking a cake. You mix ingredients (write code), then bake (compile), then eat (run).

Real-life example: Developers compile their code into apps.

School example: Students compile their first program.

Home example: Families compile small tools.

Nigerian example: Businesses compile their software.

Illustration:

  Compile and Run:

  zig build-exe hello.zig    // compile
  ./hello                     // run (Linux/Mac)
  hello.exe                   // run (Windows)

  Or simply:

  zig run hello.zig           // compile and run
  

Step-by-step:

  1. Open a terminal.
  2. Type zig run hello.zig.
  3. See the output.
  4. Or use zig build-exe to create an executable.

Mini summary: Use zig run to compile and run in one step, or zig build-exe to create a program.

Lesson 14: Common Mistakes in Zig

Definition: Mistakes happen. Knowing them helps you avoid them.

Why it is important: A small mistake can stop your program.

Simple explanation: Like a spelling mistake in a sentence.

Real-life example: Developers use tools to find mistakes.

School example: Students learn from errors in their code.

Home example: Families check their code twice.

Nigerian example: Businesses test their code carefully.

Table of common mistakes:

MistakeWhat HappensHow to Fix
Missing semicolonError messageAdd ; at the end
Wrong typeError messageUse the correct type
Forgetting const/varError messageAdd the keyword
Unused variableWarning/errorRemove or use it
Forgetting importsUnknown nameAdd @import
Mismatched typesErrorConvert types properly

Mini summary: Common mistakes include missing semicolons and wrong types. Read error messages carefully.

Lesson 15: Best Practices in Zig

Definition: Best practices are good habits that make your code clean and safe.

Why it is important: Good habits prevent bugs and save time.

Simple explanation: Like keeping your room tidy. It is easier to find things.

Real-life example: Developers write clean code for their teams.

School example: Students write neat code for projects.

Home example: Families keep their tools organized.

Nigerian example: Businesses write clear code for maintenance.

List of best practices:

  • Use const by default.
  • Use clear variable names.
  • Keep functions short and focused.
  • Handle errors properly.
  • Comment your code where needed.
  • Use defer to clean up resources.
  • Format your code with zig fmt.
  • Test your code often.
  • Read error messages carefully.
  • Keep learning from the Zig community.

Mini summary: Best practices: use const, clear names, short functions, handle errors, test often.

Key Vocabulary

WordSimple Definition
ZigA modern programming language.
CompilerA tool that turns code into a program.
VariableA box that holds a value that can change.
ConstantA box that holds a value that cannot change.
Data typeWhat kind of value a variable holds.
FunctionA reusable block of code.
StructA group of related data.
EnumA list of named values.
ArrayA fixed-size list.
SliceA view into part of an array.
StringA list of characters.
LoopCode that repeats.
ConditionA test that is true or false.
ParameterAn input to a function.
ReturnThe result a function gives back.

Important Concepts

  • Zig is modern: Simple, fast, and safe.
  • Install with PATH: Then use zig version.
  • First program: Prints “Hello, Zig!”.
  • Variables and constants: Use var and const.
  • Data types: u8, i32, f64, bool, []u8.
  • Control flow: if, switch, while, for.
  • Functions: Reusable blocks with fn.
  • Structs and enums: Group data and list named values.
  • Arrays and slices: Lists of values.
  • Compile and run: Use zig run.

Step-by-step Explanations

How to install Zig step by step

  1. Visit ziglang.org.
  2. Download the correct version.
  3. Extract to a folder.
  4. Add the folder to PATH.
  5. Run zig version.

How to write your first program step by step

  1. Create hello.zig.
  2. Type the code.
  3. Save the file.
  4. Run zig run hello.zig.
  5. See the output.

How to create a variable step by step

  1. Type var or const.
  2. Give a name.
  3. Add a colon and a type.
  4. Assign a value with =.
  5. End with ;.

How to write a function step by step

  1. Type fn.
  2. Give the function a name.
  3. Add parameters in parentheses.
  4. Add return type.
  5. Write the body with return.

How to run a loop step by step

  1. Choose while or for.
  2. Set the condition or list.
  3. Write the body.
  4. Make sure the loop ends.
  5. Test with small numbers.

Real-life Examples

  • Games: Use loops for animations.
  • Banks: Use structs for customer data.
  • Schools: Use arrays for scores.
  • Homes: Use functions for calculations.
  • Businesses: Use enums for categories.

Nigerian Examples

  • Banks: Nigerian banks use Zig for fast systems.
  • Startups: Nigerian startups build tools with Zig.
  • Schools: Nigerian students learn Zig in coding clubs.
  • Businesses: Nigerian businesses use Zig for efficiency.
  • Freelancers: Nigerian developers use Zig for projects.

Fun Examples Children Can Relate To

  • Games: Write a simple guessing game.
  • Stories: Print a story on screen.
  • Math: Build a calculator.
  • Lists: Organize your toys in code.
  • Quizzes: Build a quiz program.

Everyday Examples

  • Shopping: Add up prices.
  • Homework: Calculate averages.
  • Family: Track chores.
  • Time: Print a countdown.
  • Money: Track savings.

Parent Tips

  • Encourage your child to code every day.
  • Help them install Zig properly.
  • Celebrate their first program.
  • Be patient with errors.
  • Read error messages together.
  • Let them teach you what they learned.
  • Use examples from daily life.
  • Keep it fun and simple.
  • Encourage practice with small projects.
  • Support their learning journey.

Interesting Facts

  • Zig was first released in 2016.
  • Zig can compile C and C++ code.
  • Zig has no hidden memory allocations.
  • Zig uses comptime for compile-time code.
  • Zig is used by companies like Uber and Bun.
  • Zig is open source.
  • Zig has a built-in formatter.
  • Zig is growing fast.

Did You Know?

  • Did you know that Zig can replace C compilers?
  • Did you know that Zig has no garbage collector?
  • Did you know that Zig uses try and catch for errors?
  • Did you know that Zig supports cross-compilation easily?
  • Did you know that Zig has a standard library called std?
  • Did you know that Zig can run on tiny devices?
  • Did you know that Zig is used in game development?
  • Did you know that Nigeria has Zig developers?

Remember This

  • Zig is a modern programming language.
  • Install Zig from ziglang.org.
  • Use var for variables and const for constants.
  • Types include u8, i32, f64, bool, []u8.
  • Use if, switch, while, and for for control flow.
  • Functions are reusable blocks of code.
  • Structs group data; enums list named values.
  • Arrays hold lists; slices view parts.
  • Strings are slices of bytes.
  • Run code with zig run.

Common Mistakes

  • Missing semicolons.
  • Wrong data types.
  • Forgetting var or const.
  • Unused variables.
  • Missing imports.
  • Type mismatches.
  • Infinite loops.
  • Not reading error messages.

Best Practices

  • Use const by default.
  • Use clear variable names.
  • Keep functions short.
  • Handle errors properly.
  • Comment where needed.
  • Use defer for cleanup.
  • Format with zig fmt.
  • Test often.
  • Read error messages carefully.
  • Keep learning.

Illustrations and Diagrams

Zig Program Structure

  hello.zig
  +---------------------------+
  | @import("std")            |
  +---------------------------+
  | pub fn main() void {      |
  |     print("Hello, Zig!")  |
  | }                         |
  +---------------------------+
  

Variables vs Constants

  var age: u8 = 13;      // Can change
  const pi: f32 = 3.14;  // Cannot change
  

Control Flow

  if (score >= 70) {
      Pass
  } else {
      Fail
  }
  

Loop Structure

  while (i <= 5) : (i += 1) {
      print(i)
  }
  

Function Diagram

  Input → Function → Output
    3, 4    add()      7
  

Your Learning Journey

  Module 1: Zig Basics
        |
        V
  Module 2: Memory & Errors
        |
        V
  Module 3: Advanced Features
        |
        V
  Module 4: Real Projects
        |
        V
  Zig Expert 🎉
  

Comparison Tables

Zig vs Python vs C

FeatureZigPythonC
SpeedVery FastSlowVery Fast
SafetyHighHighLow
MemoryManualAutomaticManual
LearningMediumEasyHard

var vs const

Featurevarconst
Can change?YesNo
Use forChanging valuesFixed values
Best practiceOnly when neededDefault choice

Array vs Slice

FeatureArraySlice
SizeFixedCan vary
Owns dataYesNo
Best forFixed listsPassing parts

Struct vs Enum

FeatureStructEnum
PurposeGroup dataList choices
ExamplePerson { name, age }Color { red, green }
UseComplex objectsNamed values

Lesson Summaries

Lesson 1: Zig is a modern programming language.

Lesson 2: Zig is fast, safe, simple, and powerful.

Lesson 3: Install Zig from ziglang.org and check with zig version.

Lesson 4: Your first program prints “Hello, Zig!”.

Lesson 5: Use var for variables and const for constants.

Lesson 6: Zig types include u8, i32, f64, bool, []u8.

Lesson 7: Use if and switch for decisions.

Lesson 8: Use while and for for loops.

Lesson 9: Functions are reusable blocks of code.

Lesson 10: Structs group data; enums list named values.

Lesson 11: Arrays hold lists; slices view parts.

Lesson 12: Strings are slices of bytes.

Lesson 13: Compile and run with zig run.

Lesson 14: Common mistakes include missing semicolons.

Lesson 15: Best practices: use const, clear names, test often.

End-of-Module Summary

Congratulations! You have finished Module One of the Certified Zig Programming Expert course. You learned what Zig is and why it is special. You learned how to install Zig and write your first program. You learned about variables, constants, and data types. You learned control flow with if, switch, while, and for. You learned about functions, structs, enums, arrays, slices, and strings. You learned how to compile and run Zig programs. You learned common mistakes and best practices. Most importantly, you now have a solid foundation in Zig. In the next module, you will learn about memory management and error handling. Keep practising, and you will become a Zig expert!

Frequently Asked Questions

  1. What is Zig? A modern programming language.
  2. Why learn Zig? It is fast, safe, simple, and powerful.
  3. How do I install Zig? Download from ziglang.org and add to PATH.
  4. How do I run a Zig program? Use zig run file.zig.
  5. What is the difference between var and const? var can change; const cannot.
  6. What are Zig's data types? u8, i32, f64, bool, []u8, and more.
  7. How do I write a function? Use fn with parameters and return type.
  8. What is a struct? A group of related data.
  9. What is an enum? A list of named values.
  10. How do I handle errors? Use try and catch (in later modules).

Matching Exercises

Match the term to its meaning.

TermMeaning
1. ZigA. A group of related data
2. VariableB. A modern programming language
3. FunctionC. A box that can change
4. StructD. A reusable block of code
5. EnumE. A list of named values

Answers: 1-B, 2-C, 3-D, 4-A, 5-E

Scenario-based Exercises

  1. Scenario: You want to store a student's name. What do you use?
    Answer: A constant string: const name = "Ada";
  2. Scenario: You want to store a score that can change. What do you use?
    Answer: A variable: var score: u8 = 70;
  3. Scenario: You want to choose between pass and fail. What do you use?
    Answer: if statement.
  4. Scenario: You want to add up five numbers. What do you use?
    Answer: A for loop with a function.
  5. Scenario: You want to list colors. What do you use?
    Answer: An enum.

Group Activity

Title: “Write a Simple Calculator Together”

Instructions: In groups of 3–4, write a Zig program that adds, subtracts, multiplies, and divides two numbers. One person writes the code, one person tests it, one person fixes errors, and one person presents. Share your calculator with the class.

Goal: Practice using functions, variables, and control flow.

Individual Activity

Task: Write a Zig program that:

  • Creates a constant with your name.
  • Creates a variable with your age.
  • Prints both to the screen.
  • Uses an if statement to check if your age is above 12.

Hint: Use std.debug.print with {s} and {d}.

Mini Project

Project: “My First Zig Program”

Write a Zig program that does the following:

  • Prints a greeting with your name.
  • Prints your age.
  • Prints whether you are a teenager.
  • Uses a loop to count from 1 to 5.
  • Uses a function to add two numbers.
  • Uses a struct to describe yourself.

Example output:

  Hello, my name is Ada.
  I am 13 years old.
  I am a teenager.
  Count: 1 2 3 4 5
  Sum: 7
  Person: Ada, age 13
  

Practical Assignment

Assignment: Write a Zig program that acts as a simple quiz. The program should:

  1. Store three questions and answers in variables.
  2. Print the questions to the screen.
  3. Use if statements to check answers.
  4. Print a score at the end.
  5. Use at least one function and one struct.
  6. Add comments to explain your code.

Submit: Your .zig file and a screenshot of the output.

Key Takeaways

  • Zig is a modern programming language.
  • Install from ziglang.org.
  • Use var and const for variables and constants.
  • Types include u8, i32, f64, bool, []u8.
  • Control flow: if, switch, while, for.
  • Functions are reusable blocks.
  • Structs group data; enums list named values.
  • Arrays hold lists; slices view parts.
  • Strings are slices of bytes.
  • Run code with zig run.

Classroom Discussion Questions

  1. What is Zig, and why is it special?
  2. How do you install Zig?
  3. What is the difference between a variable and a constant?
  4. What are the main data types in Zig?
  5. How do you make decisions in Zig?
  6. How do you repeat code in Zig?
  7. What is a function, and why is it useful?
  8. What is a struct, and what is an enum?
  9. What is the difference between an array and a slice?
  10. What did Chidi learn from writing his first program?

Preparation for Module Two

In Module Two, we will learn about memory management and error handling in Zig. We will cover:

  • Pointers and memory layout.
  • Allocators (GeneralPurposeAllocator, ArenaAllocator).
  • Manual memory management and defer/errdefer.
  • Optionals (?T) and error unions (!T).
  • try, catch, and error handling patterns.
  • Comptime basics and generics.

To prepare, make sure you have completed the practical assignment and have your Zig environment ready. Review the key vocabulary. Think about how memory works in a computer. Bring your curiosity!

See you in Module Two!


End of Module One – Certified Zig Programming Expert

3

Module Two

Certified Zig Programming Expert – Module Two

Module Two: Memory Management and Error Handling – Being the Boss of Your Computer's Memory

“Certified Zig Programming Expert” – Master the language of modern systems programming

Module Introduction

Welcome back, young Zig programmer! In Module One, you learned what Zig is, how to install it, and how to write your first programs. You learned about variables, constants, data types, control flow, functions, structs, enums, arrays, slices, and strings. You have built a strong foundation.

Now it is time to learn something very important: memory management and error handling. Every computer has memory, which is like a giant warehouse where programs store their data. In some languages, the computer manages memory for you. In Zig, you are the boss of your memory. You decide when to use it and when to free it.

This might sound scary, but it is actually very powerful. It makes your programs fast and safe. Zig also has a wonderful way of handling errors using things called optionals and error unions. These help you write programs that do not crash.

In this module, we will learn about pointers, allocators, defer, errdefer, optionals, error unions, try, catch, comptime, and generics. By the end, you will write memory-safe Zig programs with proper error handling. Let's begin!

Learning Objectives

After finishing this module, you will be able to:

  • Explain what memory is and why it matters.
  • Understand pointers and how to use them.
  • Use Zig's allocators to manage memory.
  • Use defer and errdefer to clean up resources.
  • Explain what optionals (?T) are.
  • Explain what error unions (!T) are.
  • Use try and catch for error handling.
  • Understand the basics of comptime.
  • Write simple generic functions.
  • Complete a mini project and practical assignment.

Warm-up Story: Ngozi’s Memory Warehouse

Ngozi is 14 years old and lives in Enugu. She has been learning Zig with her older brother. One day, her brother said, “Ngozi, let me teach you about memory. Imagine your computer has a giant warehouse. Every time you create a variable, you take a box from the warehouse and put something inside.”

Ngozi understood. “So when I write var age: u8 = 13;, I am taking a small box and putting the number 13 in it?” she asked. “Exactly!” her brother said.

“But what happens if I take too many boxes and never return them?” Ngozi asked. “That is called a memory leak,” her brother said. “The warehouse runs out of boxes, and the computer slows down. In Zig, you must return the boxes when you are done.”

Ngozi learned about allocators, which are like warehouse managers. She learned about defer, which is a way of saying, “When I finish this task, please return the box.” She learned about try and catch, which help her handle problems gracefully.

By the end of the day, Ngozi had written a small program that used memory carefully. Nothing leaked, and nothing crashed. Her brother said, “You are becoming a real Zig programmer!”

Moral of the story: In Zig, you are the boss of memory. You decide when to take it and when to give it back. Zig's tools (allocators, defer, try, catch) help you do this safely.

Main Lessons

Lesson 1: What is Memory?

Definition: Memory is the part of a computer where programs store data while they are running.

Why it is important: Without memory, programs cannot store or use data.

Simple explanation: Imagine a giant warehouse with many boxes. Each box holds a piece of data.

Real-life example: A bank stores customer balances in memory.

School example: A school stores student scores in memory.

Home example: A family stores a shopping list in memory.

Nigerian example: A trader stores the day’s sales in memory.

Illustration:

  Memory = Giant Warehouse
  +------+  +------+  +------+  +------+
  | Box1 |  | Box2 |  | Box3 |  | Box4 |
  +------+  +------+  +------+  +------+
     |        |         |         |
   age=13   name="Ada"  score=90  price=500
  

Mini summary: Memory is where programs store data. It is like a warehouse full of boxes.

Lesson 2: What is a Pointer?

Definition: A pointer is a variable that holds the address of another variable in memory.

Why it is important: Pointers let you access and change data in memory directly.

Simple explanation: Imagine a box with a note inside that says, “Look in Box 5.” That is a pointer.

Real-life example: A bank uses pointers to find customer accounts quickly.

School example: A teacher uses pointers to find student records.

Home example: A family uses pointers to find items in storage.

Nigerian example: A trader uses pointers to find products in a warehouse.

Illustration:

  Pointer Example:

  var age: u8 = 13;
  const ptr = &age;   // ptr points to age

  std.debug.print("{d}\n", .{ptr.*});   // prints 13

  &  = "address of"
  .* = "value at"
  

Step-by-step:

  1. Create a variable.
  2. Use & to get its address.
  3. Store the address in a pointer.
  4. Use .* to get the value through the pointer.

Mini summary: A pointer holds an address. Use & to get addresses and .* to get values.

Lesson 3: What is an Allocator?

Definition: An allocator is a tool that gives your program memory when it needs it.

Why it is important: Allocators manage memory carefully so your program does not waste it.

Simple explanation: Like a librarian who gives you books and takes them back when you are done.

Real-life example: Banks use allocators to handle many transactions.

School example: Schools use allocators for student data.

Home example: Families use allocators for shopping lists that grow.

Nigerian example: Businesses use allocators for growing sales data.

Illustration:

  Allocator = Memory Manager

  Program → Allocator → Memory
              |
              V
  "Give me 100 bytes"
              |
              V
  "Here you go" → Use → "Free it"
  

Mini summary: Allocators provide and manage memory. They are essential for growing data.

Lesson 4: GeneralPurposeAllocator

Definition: GeneralPurposeAllocator is Zig's general-purpose memory manager. It is safe and detects memory leaks.

Why it is important: It is the recommended allocator for most programs.

Simple explanation: Like a smart warehouse manager who tracks every box you take and reminds you to return it.

Real-life example: Banks use it to track all memory usage.

School example: Schools use it to avoid leaks.

Home example: Families use it to keep memory clean.

Nigerian example: Businesses use it for safe programs.

Illustration:

  Using GeneralPurposeAllocator:

  var gpa = std.heap.GeneralPurposeAllocator(.{}){};
  defer _ = gpa.deinit();

  const allocator = gpa.allocator();

  const memory = try allocator.alloc(u8, 10);
  defer allocator.free(memory);
  

Step-by-step:

  1. Create a GeneralPurposeAllocator.
  2. Use defer to clean it up.
  3. Get the allocator with .allocator().
  4. Use alloc to get memory.
  5. Use free to release it (often with defer).

Mini summary: GeneralPurposeAllocator is the recommended allocator. It tracks memory and detects leaks.

Lesson 5: ArenaAllocator

Definition: ArenaAllocator is an allocator that frees all memory at once.

Why it is important: It is fast and simple for short-lived tasks.

Simple explanation: Like using a big box, then throwing the whole box away when done.

Real-life example: Banks use it for one-time tasks.

School example: Schools use it for one-time reports.

Home example: Families use it for one-time lists.

Nigerian example: Traders use it for daily summaries.

Illustration:

  Using ArenaAllocator:

  var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator);
  defer arena.deinit();

  const allocator = arena.allocator();

  _ = try allocator.alloc(u8, 100);
  _ = try allocator.alloc(u8, 200);
  // All freed when arena.deinit() runs
  

Step-by-step:

  1. Create an ArenaAllocator.
  2. Use defer to free everything at the end.
  3. Get the allocator.
  4. Use memory freely.
  5. All memory is freed at once when the arena is deinitialized.

Mini summary: ArenaAllocator frees all memory at once. It is fast and simple.

Lesson 6: defer and errdefer

Definition: defer runs code when a block ends. errdefer runs only when an error occurs.

Why it is important: They ensure cleanup always happens.

Simple explanation: Like setting an alarm to remind you to lock the door when you leave.

Real-life example: Banks use defer to close files.

School example: Schools use defer to close books.

Home example: Families use defer to turn off lights.

Nigerian example: Businesses use defer to release resources.

Illustration:

  defer:

  const file = try openFile("data.txt");
  defer file.close();   // runs at end of block

  errdefer:

  const memory = try allocator.alloc(u8, 10);
  errdefer allocator.free(memory);   // runs if error
  

Step-by-step:

  1. Use defer right after you take a resource.
  2. Use errdefer when you only want cleanup on errors.
  3. They run when the function or block ends.
  4. They run in reverse order (last one first).

Mini summary: defer runs at block end. errdefer runs only on error. They ensure cleanup.

Lesson 7: Optionals (?T)

Definition: An optional is a value that might or might not exist. It is written as ?T.

Why it is important: Optionals let you handle missing values safely.

Simple explanation: Like a box that might be empty or might have something inside.

Real-life example: A bank looks up an account that might not exist.

School example: A teacher looks up a student who might not be enrolled.

Home example: A family looks up a phone number that might be missing.

Nigerian example: A trader looks up a price that might not be set.

Illustration:

  Optional Example:

  var maybe_age: ?u8 = null;
  maybe_age = 13;

  if (maybe_age) |age| {
      std.debug.print("Age: {d}\n", .{age});
  } else {
      std.debug.print("No age given.\n", .{});
  }
  

Step-by-step:

  1. Use ?T to declare an optional.
  2. Set it to null for empty.
  3. Use if (maybe) |value| to get the value.
  4. Use else for the missing case.

Mini summary: Optionals are values that might be missing. Use ?T and handle both cases.

Lesson 8: Error Unions (!T)

Definition: An error union is a value that is either a result or an error. It is written as !T.

Why it is important: Error unions let functions report problems cleanly.

Simple explanation: Like a package that might be delivered or might be lost.

Real-life example: A bank transfers money that might fail.

School example: A teacher grades a test that might have errors.

Home example: A family buys an item that might be out of stock.

Nigerian example: A trader sells an item that might be unavailable.

Illustration:

  Error Union Example:

  fn divide(a: i32, b: i32) !i32 {
      if (b == 0) return error.DivideByZero;
      return a / b;
  }

  const result = divide(10, 2) catch |err| {
      std.debug.print("Error: {}\n", .{err});
      return;
  };
  

Step-by-step:

  1. Use !T as the return type.
  2. Return errors with error.Name.
  3. Handle them with try or catch.

Mini summary: Error unions report results or errors. Use !T and handle both cases.

Lesson 9: try and catch

Definition: try passes an error up. catch handles it here.

Why it is important: They make error handling clean and clear.

Simple explanation: Like passing a problem to your teacher (try) or solving it yourself (catch).

Real-life example: Banks use try to pass errors up.

School example: Schools use try in functions.

Home example: Families use catch to handle problems.

Nigerian example: Businesses use try in their code.

Illustration:

  try:

  fn doWork() !void {
      const data = try readFile("data.txt");
      std.debug.print("Got data: {s}\n", .{data});
  }

  catch:

  const data = readFile("data.txt") catch |err| {
      std.debug.print("Failed: {}\n", .{err});
      return;
  };
  

Step-by-step:

  1. Use try to propagate errors up.
  2. Use catch to handle errors locally.
  3. Use catch |err| to get the error value.
  4. Use catch unreachable only if you are sure there is no error.

Mini summary: try passes errors up; catch handles them. Use them to control errors.

Lesson 10: Introduction to comptime

Definition: comptime means code that runs while the program is being compiled, not while it is running.

Why it is important: comptime makes programs faster and safer.

Simple explanation: Like preparing ingredients before cooking, instead of during cooking.

Real-life example: Banks precompute interest tables.

School example: Schools precompute timetables.

Home example: Families prepare meals in advance.

Nigerian example: Traders prepare price lists in advance.

Illustration:

  comptime Example:

  const size = comptime 5 + 5;   // computed at compile time

  fn makeArray() [size]u8 {
      return [_]u8{0} ** size;
  }
  

Step-by-step:

  1. Use comptime before a value or block.
  2. The compiler computes it.
  3. Use it for sizes, constants, and types.

Mini summary: comptime runs at compile time. It makes programs faster and safer.

Lesson 11: Generics in Zig

Definition: Generics are functions or types that work with many types.

Why it is important: Generics let you write code once and use it with many types.

Simple explanation: Like a single tool that fits many sizes.

Real-life example: Banks use generic functions for different account types.

School example: Schools use generic functions for different subjects.

Home example: Families use generic containers for different items.

Nigerian example: Traders use generic lists for different products.

Illustration:

  Generic Function:

  fn add(comptime T: type, a: T, b: T) T {
      return a + b;
  }

  const x = add(i32, 3, 4);   // 7
  const y = add(f64, 3.5, 4.5); // 8.0
  

Step-by-step:

  1. Use comptime T: type as a parameter.
  2. Use T in the rest of the function.
  3. Call with a specific type.

Mini summary: Generics let you write one function for many types. Use comptime T: type.

Lesson 12: Common Mistakes in Memory and Errors

Definition: Mistakes happen. Knowing them helps you avoid them.

Why it is important: Small mistakes can cause crashes or leaks.

Simple explanation: Like forgetting to close a door.

Real-life example: Banks avoid leaks in their software.

School example: Students learn from memory errors.

Home example: Families avoid wasting resources.

Nigerian example: Businesses fix memory bugs quickly.

Table of common mistakes:

MistakeWhat HappensHow to Fix
Forgetting deferMemory leakUse defer right after allocation
Using freed memoryCrashNever use after free
Not handling errorsCrashUse try or catch
Using unreachable wronglyCrashUse only when sure
Optional without checkCrashUse if (maybe) |v|
Wrong allocator lifetimeCrashUse correct scope

Mini summary: Common mistakes: missing defer, using freed memory, ignoring errors. Fix them early.

Lesson 13: Best Practices for Memory and Errors

Definition: Best practices are good habits that keep your code clean and safe.

Why it is important: Good habits prevent bugs and crashes.

Simple explanation: Like washing your hands before cooking.

Real-life example: Banks follow strict coding rules.

School example: Students follow coding guidelines.

Home example: Families keep resources organized.

Nigerian example: Businesses use consistent code style.

List of best practices:

  • Use defer immediately after allocation.
  • Always free what you allocate.
  • Use GeneralPurposeAllocator for general use.
  • Use ArenaAllocator for short-lived tasks.
  • Handle every error.
  • Use optionals for values that might be missing.
  • Use error unions for functions that can fail.
  • Use try to propagate; catch to handle.
  • Use comptime for constants and sizes.
  • Write tests for your code.

Mini summary: Best practices: defer, free memory, handle errors, use optionals and error unions, test.

Lesson 14: Building a Safe Zig Program

Let’s build a small program that uses memory safely.

Step 1: Create a GeneralPurposeAllocator.

Step 2: Use defer to free it.

Step 3: Allocate an array of numbers.

Step 4: Use defer to free the array.

Step 5: Fill the array with values.

Step 6: Print the values.

Step 7: Use an optional to check if values exist.

Step 8: Use error union in a helper function.

Illustration:

  Safe Program Structure:

  main()
     |
     V
  GPA + defer deinit
     |
     V
  alloc() + defer free
     |
     V
  Fill data
     |
     V
  Print data
     |
     V
  Clean exit 🎉
  

Mini summary: A safe program uses allocators, defer, optionals, and error unions together.

Lesson 15: Putting It All Together – Your Memory Toolkit

You now have a powerful toolkit for memory and errors.

Your toolkit:

  • Pointers: Address of values.
  • Allocators: GeneralPurpose, Arena.
  • defer/errdefer: Cleanup on exit or error.
  • Optionals: Values that might be missing.
  • Error unions: Results or errors.
  • try/catch: Passing or handling errors.
  • comptime: Compile-time code.
  • Generics: Code for many types.

Illustration:

  Your Toolkit:
  +----------+  +----------+  +----------+
  | Pointers |  | Allocs   |  | defer    |
  +----------+  +----------+  +----------+
  +----------+  +----------+  +----------+
  | Optionals|  | !T       |  | try/catch|
  +----------+  +----------+  +----------+
  +----------+  +----------+
  | comptime |  | Generics |
  +----------+  +----------+
  

Mini summary: You now have a toolkit for memory and errors. Use it wisely.

Key Vocabulary

WordSimple Definition
MemoryWhere programs store data.
PointerA variable that holds an address.
AllocatorA tool that provides memory.
GeneralPurposeAllocatorA safe, general allocator.
ArenaAllocatorAn allocator that frees all at once.
deferRun code at block end.
errdeferRun code only on error.
OptionalA value that might be missing (?T).
Error unionA result or error (!T).
tryPass an error up.
catchHandle an error here.
comptimeCode that runs at compile time.
GenericCode that works with many types.
Memory leakMemory that is never freed.
nullEmpty optional value.

Important Concepts

  • Memory is a warehouse: Programs store data there.
  • Pointers hold addresses: Use & and .*.
  • Allocators manage memory: Use GPA or Arena.
  • defer ensures cleanup: Always runs at block end.
  • errdefer runs on error: Useful for partial cleanup.
  • Optionals handle missing values: Use ?T.
  • Error unions report problems: Use !T.
  • try and catch control errors: Pass or handle.
  • comptime makes code fast: Runs at compile time.
  • Generics work with many types: Use comptime T: type.

Step-by-step Explanations

How to use an allocator step by step

  1. Create a GeneralPurposeAllocator.
  2. Use defer _ = gpa.deinit();.
  3. Get the allocator: const allocator = gpa.allocator();.
  4. Use alloc to get memory.
  5. Use defer allocator.free(memory);.
  6. Use the memory.

How to handle an error step by step

  1. Make a function return !T.
  2. Return errors with error.Name.
  3. Use try to propagate errors.
  4. Use catch to handle them.
  5. Use catch |err| to get the error.

How to use optionals step by step

  1. Declare with ?T.
  2. Set to null for empty.
  3. Use if (maybe) |v| to unwrap.
  4. Use else for missing.

How to write a generic function step by step

  1. Use comptime T: type as a parameter.
  2. Use T in the body.
  3. Call with a specific type.

How to use comptime step by step

  1. Put comptime before a value or block.
  2. The compiler computes it.
  3. Use for sizes, constants, and types.

Real-life Examples

  • Banks: Use allocators for transactions.
  • Games: Use defer to close files.
  • Schools: Use optionals for optional data.
  • Homes: Use error unions for chores.
  • Businesses: Use comptime for constants.

Nigerian Examples

  • Banks: Nigerian banks use allocators for memory safety.
  • Startups: Startups use defer for clean code.
  • Schools: Students learn error handling early.
  • Businesses: Businesses use comptime for speed.
  • Freelancers: Freelancers use generics for reusable code.

Fun Examples Children Can Relate To

  • Games: Track scores with optionals.
  • Toys: Store toy lists with arrays.
  • Pets: Handle "pet not found" with error unions.
  • Snacks: Use defer to clean up after snacks.
  • Stories: Use generics to tell stories for any character.

Everyday Examples

  • Shopping: Handle missing prices with optionals.
  • Homework: Use try for risky steps.
  • Family: Use defer to turn off lights.
  • Time: Use comptime for fixed schedules.
  • Money: Use error unions for payments.

Parent Tips

  • Explain memory as a warehouse with boxes.
  • Teach your child to clean up after using resources.
  • Encourage them to read error messages.
  • Show them how banks use memory safely.
  • Praise them for writing safe code.
  • Practice with small programs.
  • Read Zig documentation together.
  • Keep sessions short and fun.
  • Let them teach you what they learned.
  • Support their learning journey.

Interesting Facts

  • Zig does not have a garbage collector.
  • Zig's defer runs in reverse order.
  • comptime can compute complex values.
  • Zig errors are values, not exceptions.
  • Zig supports C-style pointers.
  • Zig's allocators can be swapped easily.
  • Zig code can be faster than C.
  • Zig is used in production systems.

Did You Know?

  • Did you know that Zig can detect memory leaks?
  • Did you know that ArenaAllocator is fast?
  • Did you know that try is a shortcut for catch |err| return err?
  • Did you know that optionals replace null pointers?
  • Did you know that comptime can generate code?
  • Did you know that Zig generics are compile-time?
  • Did you know that Zig errors are checked at compile time?
  • Did you know that Nigerian developers use Zig for performance?

Remember This

  • Memory is where programs store data.
  • Pointers hold addresses.
  • Allocators provide memory.
  • Use GPA for general and Arena for short tasks.
  • defer cleans up at block end.
  • errdefer cleans up on error.
  • Optionals handle missing values.
  • Error unions report problems.
  • try passes; catch handles.
  • comptime runs at compile time.

Common Mistakes

  • Forgetting defer.
  • Using freed memory.
  • Not handling errors.
  • Using unreachable wrongly.
  • Optional without check.
  • Wrong allocator lifetime.
  • Ignoring compiler warnings.
  • Not testing code.

Best Practices

  • Use defer right after allocation.
  • Always free what you allocate.
  • Use GPA for general use.
  • Use Arena for short-lived tasks.
  • Handle every error.
  • Use optionals for missing values.
  • Use error unions for functions that can fail.
  • Use try to propagate; catch to handle.
  • Use comptime for constants and sizes.
  • Write tests.

Illustrations and Diagrams

Memory Diagram

  Memory = Warehouse

  +------+  +------+  +------+  +------+
  | Box1 |  | Box2 |  | Box3 |  | Box4 |
  +------+  +------+  +------+  +------+
     |        |         |         |
   age=13   name="Ada"  score=90  price=500
  

Pointer Diagram

  ptr → age (13)

  &  = "address of"
  .* = "value at"
  

Allocator Flow

  Program → Allocator → Memory

  Allocate → Use → Free
  

defer and errdefer

  defer → runs at end of block
  errdefer → runs only on error
  

Optional and Error Union

  Optional: ?T = value or null
  Error union: !T = value or error
  

Your Learning Journey

  Module 1: Zig Basics
        |
        V
  Module 2: Memory & Errors
        |
        V
  Module 3: Advanced Features
        |
        V
  Module 4: Real Projects
        |
        V
  Zig Expert 🎉
  

Comparison Tables

GPA vs Arena

FeatureGeneralPurposeAllocatorArenaAllocator
Frees memoryOne at a timeAll at once
SpeedModerateVery fast
Best forLong-running codeShort-lived tasks
Leak detectionYesNo

Optional vs Error Union

FeatureOptional (?T)Error Union (!T)
MeaningValue or nullValue or error
Use forMissing valuePossible failure
Handlingif (x) |v|try / catch

defer vs errdefer

Featuredefererrdefer
RunsAlwaysOnly on error
Best forCleanupPartial cleanup
OrderReverseReverse

comptime vs runtime

Featurecomptimeruntime
WhenCompile timeRun time
SpeedFastSlower
Best forConstants, sizesDynamic data

Lesson Summaries

Lesson 1: Memory is where programs store data.

Lesson 2: Pointers hold addresses of values.

Lesson 3: Allocators provide and manage memory.

Lesson 4: GeneralPurposeAllocator is safe and detects leaks.

Lesson 5: ArenaAllocator frees all memory at once.

Lesson 6: defer cleans up; errdefer cleans up on error.

Lesson 7: Optionals (?T) handle missing values.

Lesson 8: Error unions (!T) report results or errors.

Lesson 9: try passes errors; catch handles them.

Lesson 10: comptime runs at compile time.

Lesson 11: Generics work with many types.

Lesson 12: Common mistakes: missing defer, using freed memory.

Lesson 13: Best practices: defer, free memory, handle errors.

Lesson 14: Build a safe program with allocators and errors.

Lesson 15: Your toolkit includes pointers, allocators, optionals, errors, comptime, generics.

End-of-Module Summary

Congratulations! You have finished Module Two of the Certified Zig Programming Expert course. You learned what memory is and how to use pointers. You learned about allocators (GeneralPurposeAllocator and ArenaAllocator). You learned about defer and errdefer for cleanup. You learned about optionals and error unions. You learned to use try and catch. You learned the basics of comptime and generics. You learned common mistakes and best practices. Most importantly, you now know how to write memory-safe Zig programs with proper error handling. In the next module, you will learn about advanced features and the standard library. Keep practising, and you will become a Zig expert!

Frequently Asked Questions

  1. What is memory? Where programs store data while running.
  2. What is a pointer? A variable that holds an address.
  3. What is an allocator? A tool that provides memory.
  4. What is the difference between GPA and Arena? GPA frees one at a time; Arena frees all at once.
  5. What is defer? Code that runs at block end.
  6. What is errdefer? Code that runs only on error.
  7. What is an optional? A value that might be missing (?T).
  8. What is an error union? A result or error (!T).
  9. What is comptime? Code that runs at compile time.
  10. What is a generic? Code that works with many types.

Matching Exercises

Match the term to its meaning.

TermMeaning
1. PointerA. Runs at block end
2. AllocatorB. Value or null
3. deferC. Holds an address
4. OptionalD. Provides memory
5. Error unionE. Value or error

Answers: 1-C, 2-D, 3-A, 4-B, 5-E

Scenario-based Exercises

  1. Scenario: You want to get the address of a variable. What do you use?
    Answer: The & operator.
  2. Scenario: You want to allocate an array of numbers. What do you do?
    Answer: Use an allocator with alloc(u8, N).
  3. Scenario: You want to clean up memory when a block ends. What do you use?
    Answer: defer.
  4. Scenario: Your function might fail. What return type do you use?
    Answer: !T (error union).
  5. Scenario: You want a value that might be missing. What do you use?
    Answer: ?T (optional).

Group Activity

Title: “Write a Safe Memory Program Together”

Instructions: In groups of 3–4, write a Zig program that uses an allocator to create an array, fills it with numbers, prints them, and frees the memory. Add a function that returns an error union, and handle the error with try/catch. One person writes, one person tests, one person fixes, and one person presents. Share your program with the class.

Goal: Practice using allocators, defer, and error handling.

Individual Activity

Task: Write a Zig program that:

  • Uses a GeneralPurposeAllocator.
  • Allocates an array of 5 u8 values.
  • Fills them with numbers.
  • Prints them.
  • Uses defer to free memory.
  • Uses an optional to check if a value exists.
  • Uses try in a helper function.

Hint: Start with a small program and add features one at a time.

Mini Project

Project: “Safe Memory Manager”

Write a Zig program that:

  • Creates a GeneralPurposeAllocator.
  • Uses defer to deinitialize the allocator.
  • Allocates memory for a string.
  • Fills the string with "Hello, Zig!".
  • Uses defer to free the string.
  • Prints the string.
  • Uses an optional to store the string length.
  • Uses an error union in a helper function.

Example output:

  Message: Hello, Zig!
  Length: 11
  All done safely 🎉
  

Practical Assignment

Assignment: Write a Zig program that acts as a small inventory system. The program should:

  1. Use an ArenaAllocator.
  2. Create a struct for an item (name, price, quantity).
  3. Allocate an array of 5 items.
  4. Fill them with sample data.
  5. Calculate the total value.
  6. Use an optional to check if any item exists.
  7. Use an error union for a lookup function.
  8. Handle errors with try and catch.
  9. Free all memory with defer.
  10. Print a summary.

Submit: Your .zig file and a screenshot of the output.

Key Takeaways

  • Memory is where programs store data.
  • Pointers hold addresses.
  • Allocators provide memory.
  • Use GPA for general and Arena for short tasks.
  • defer cleans up at block end.
  • errdefer cleans up on error.
  • Optionals handle missing values.
  • Error unions report problems.
  • try passes; catch handles.
  • comptime runs at compile time.

Classroom Discussion Questions

  1. Why is memory important in programming?
  2. What is a pointer, and how do you use it?
  3. What is an allocator, and why does Zig use them?
  4. What is the difference between GPA and Arena?
  5. Why is defer useful?
  6. When would you use errdefer?
  7. What is an optional, and when do you use it?
  8. What is an error union, and why is it useful?
  9. What does comptime do, and why does it matter?
  10. What did Ngozi learn from her memory warehouse?

Preparation for Module Three

In Module Three, we will learn about advanced features and the standard library. We will cover:

  • Advanced comptime metaprogramming.
  • Generics and compile-time reflection.
  • Zig Build System (build.zig).
  • Unit testing and test blocks.
  • Zig Standard Library tour.
  • Interfacing with C (C ABI, @cImport).

To prepare, make sure you have completed the practical assignment and have your Zig environment ready. Review the key vocabulary. Think about how you would build larger programs. Bring your curiosity!

See you in Module Three!


End of Module Two – Certified Zig Programming Expert

4

Module Three

Certified Zig Programming Expert – Module Three

Module Three: Advanced Features and the Standard Library – Becoming a Zig Power User

“Certified Zig Programming Expert” – Master the language of modern systems programming

Module Introduction

Welcome back, young Zig programmer! In Module One, you learned the basics of Zig: variables, functions, structs, enums, arrays, slices, and strings. In Module Two, you learned about memory management and error handling: pointers, allocators, defer, optionals, error unions, try, catch, comptime, and generics.

Now it is time to go deeper. In Module Three, we will learn about advanced features and the standard library. This is where Zig becomes truly powerful. We will explore advanced comptime metaprogramming, the Zig Build System, unit testing, the standard library, and how to work with C code.

Think of this module as moving from a small workshop to a large factory. You will learn to build bigger, more complex programs. You will learn to organize your code, test it, and use the many tools Zig provides. By the end of this module, you will be a Zig power user.

Let's begin!

Learning Objectives

After finishing this module, you will be able to:

  • Use advanced comptime features.
  • Write and use generic functions and types.
  • Use compile-time reflection with @typeInfo.
  • Understand the Zig Build System (build.zig).
  • Write unit tests using test blocks.
  • Explore the Zig Standard Library (std).
  • Work with files, strings, and collections.
  • Use @import to organize code.
  • Interface with C using @cImport and the C ABI.
  • Complete a mini project and practical assignment.

Warm-up Story: Ada’s Big Project

Ada is 15 years old and lives in Abuja. She has been learning Zig for a few weeks and has built several small programs. Now she wants to build something bigger: a small tool that helps her father’s shop keep track of inventory.

Ada started writing code, but it quickly became messy. She had one big file with hundreds of lines. She had no tests, and she kept making the same mistakes. She also needed to use code from a C library her father already had.

Her mentor said, “Ada, it is time to learn advanced Zig. You will learn how to organize your code into modules, use the build system, write tests, and even use C libraries. This is how real programmers build big projects.”

Ada learned about the Zig Build System and created a build.zig file. She split her code into several files using @import. She wrote tests using test blocks. She used the standard library for file handling. And she learned how to call C functions using @cImport.

By the end of the week, Ada’s inventory tool was clean, tested, and ready to use. Her father was very proud. Ada had become a Zig power user.

Moral of the story: Advanced Zig features let you build bigger, cleaner, and more powerful programs. Learn the build system, testing, the standard library, and C interop to become a true expert.

Main Lessons

Lesson 1: Advanced comptime Metaprogramming

Definition: comptime metaprogramming is writing code that runs at compile time and can generate or modify other code.

Why it is important: It makes programs faster and lets you write flexible code.

Simple explanation: Imagine writing a recipe that writes other recipes. That is what comptime can do.

Real-life example: Banks use comptime to generate efficient code.

School example: Schools use comptime for generating timetables.

Home example: Families use comptime for meal planning.

Nigerian example: Businesses use comptime for pricing rules.

Illustration:

  comptime Metaprogramming:

  fn power(comptime n: u8, x: i32) i32 {
      if (n == 0) return 1;
      return x * power(n - 1, x);
  }

  const result = comptime power(3, 2);  // 8 at compile time
  

Step-by-step:

  1. Mark parameters with comptime.
  2. Write recursion or loops.
  3. Call with comptime to evaluate.
  4. Use the result at runtime.

Mini summary: Advanced comptime lets you generate code at compile time. It makes programs faster.

Lesson 2: Generic Functions and Types

Definition: Generics let you write code that works with many types.

Why it is important: Generics let you write code once and reuse it.

Simple explanation: Like a shirt that fits any size.

Real-life example: Banks use generic functions for different account types.

School example: Schools use generic containers for different subjects.

Home example: Families use generic lists for different items.

Nigerian example: Traders use generic lists for different products.

Illustration:

  Generic Function:

  fn max(comptime T: type, a: T, b: T) T {
      return if (a > b) a else b;
  }

  const m1 = max(i32, 3, 7);      // 7
  const m2 = max(f64, 3.5, 2.1);  // 3.5

  Generic Struct:

  fn Pair(comptime T: type) type {
      return struct {
          first: T,
          second: T,
      };
  }

  const IntPair = Pair(i32);
  

Step-by-step:

  1. Use comptime T: type for the type.
  2. Use T in the function body.
  3. For generic types, return a struct from a function.
  4. Call with a specific type.

Mini summary: Generics let you write code for many types. Use comptime T: type.

Lesson 3: Compile-Time Reflection with @typeInfo

Definition: @typeInfo gives you information about a type at compile time.

Why it is important: It lets you write code that adapts to any type.

Simple explanation: Like a magnifying glass that shows you what a type is made of.

Real-life example: Banks use reflection to print reports for any data type.

School example: Schools use reflection for generic printing.

Home example: Families use reflection for flexible logs.

Nigerian example: Businesses use reflection for generic reports.

Illustration:

  @typeInfo Example:

  fn describe(comptime T: type) void {
      const info = @typeInfo(T);
      switch (info) {
          .Int => std.debug.print("It's an integer!\n", .{}),
          .Float => std.debug.print("It's a float!\n", .{}),
          .Struct => std.debug.print("It's a struct!\n", .{}),
          else => std.debug.print("Something else.\n", .{}),
      }
  }

  describe(i32);   // It's an integer!
  describe(f64);   // It's a float!
  

Step-by-step:

  1. Use @typeInfo(T) to get info.
  2. Switch on the kind of type.
  3. Handle each kind.

Mini summary: @typeInfo gives type info at compile time. It enables powerful generic code.

Lesson 4: The Zig Build System (build.zig)

Definition: The Zig Build System is a way to organize and build complex Zig projects.

Why it is important: It handles dependencies, targets, and compilation steps.

Simple explanation: Like a recipe for building your entire project.

Real-life example: Banks use build systems for their software.

School example: Schools use build systems for class projects.

Home example: Families use build systems for home automation.

Nigerian example: Businesses use build systems for their tools.

Illustration:

  build.zig Example:

  const std = @import("std");

  pub fn build(b: *std.Build) void {
      const target = b.standardTargetOptions(.{});
      const optimize = b.standardOptimizeOption(.{});

      const exe = b.addExecutable(.{
          .name = "myprogram",
          .root_source_file = b.path("src/main.zig"),
          .target = target,
          .optimize = optimize,
      });
      b.installArtifact(exe);

      const run_cmd = b.addRunArtifact(exe);
      const run_step = b.step("run", "Run the program");
      run_step.dependOn(&run_cmd.step);
  }
  

Step-by-step:

  1. Create a build.zig file.
  2. Define the executable or library.
  3. Set source file, target, and optimize options.
  4. Add install and run steps.
  5. Run zig build or zig build run.

Mini summary: The build system organizes complex projects. Use build.zig and zig build.

Lesson 5: Writing Unit Tests

Definition: Unit tests are small programs that check if your code works.

Why it is important: Tests catch bugs early.

Simple explanation: Like checking your homework before submitting it.

Real-life example: Banks test their software before use.

School example: Students check their answers.

Home example: Families test appliances.

Nigerian example: Businesses test products.

Illustration:

  Test Example:

  const std = @import("std");

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

  test "add works" {
      try std.testing.expect(add(2, 3) == 5);
      try std.testing.expect(add(-1, 1) == 0);
  }

  Run with: zig test src/main.zig
  

Step-by-step:

  1. Import std.
  2. Write test "description" { ... }.
  3. Use try std.testing.expect(...).
  4. Run with zig test.

Mini summary: Tests verify your code. Write them with test blocks and run with zig test.

Lesson 6: The Zig Standard Library (std)

Definition: The standard library is a collection of ready-made code that comes with Zig.

Why it is important: It saves time and gives you tested tools.

Simple explanation: Like a toolbox full of useful tools.

Real-life example: Banks use std for logging.

School example: Schools use std for file handling.

Home example: Families use std for timing tasks.

Nigerian example: Businesses use std for networking.

Illustration:

  Common std Modules:

  std.debug   → printing and debugging
  std.heap    → memory allocators
  std.fs      → file system
  std.mem     → memory operations
  std.fmt     → formatting
  std.math    → math functions
  std.testing → testing tools
  std.Thread  → threading
  std.net     → networking
  

Mini summary: The standard library std provides many useful tools. Learn it to save time.

Lesson 7: Working with Files

Definition: File handling means reading from and writing to files on your computer.

Why it is important: Files let you save data permanently.

Simple explanation: Like saving your work in a notebook.

Real-life example: Banks save transaction records in files.

School example: Schools save student data in files.

Home example: Families save shopping lists in files.

Nigerian example: Businesses save sales in files.

Illustration:

  Reading a File:

  const std = @import("std");

  pub fn main() !void {
      const file = try std.fs.cwd().openFile("data.txt", .{});
      defer file.close();

      var buffer: [1024]u8 = undefined;
      const bytes = try file.readAll(&buffer);
      std.debug.print("Read: {s}\n", .{buffer[0..bytes]});
  }

  Writing a File:

  const file = try std.fs.cwd().createFile("out.txt", .{});
  defer file.close();
  try file.writeAll("Hello, file!\n");
  

Step-by-step:

  1. Open or create a file.
  2. Use defer file.close().
  3. Read with readAll or write with writeAll.
  4. Handle errors with try.

Mini summary: Use std.fs for files. Always close with defer.

Lesson 8: Working with Strings

Definition: Strings are lists of characters. Zig stores them as []const u8.

Why it is important: Strings handle text in your programs.

Simple explanation: Like writing words with letters.

Real-life example: Banks store names and addresses as strings.

School example: Schools store student names as strings.

Home example: Families store messages as strings.

Nigerian example: Businesses store product names as strings.

Illustration:

  String Operations:

  const std = @import("std");

  const name = "Ada";
  const greeting = try std.fmt.allocPrint(
      allocator, "Hello, {s}!", .{name}
  );
  defer allocator.free(greeting);

  std.debug.print("{s}\n", .{greeting});

  Common std.mem functions:
  - eql(a, b)      → equal?
  - startsWith(a, b) → starts with?
  - indexOf(a, b)  → find position
  - split(a, b)    → split by delimiter
  - trim(a, b)     → remove whitespace
  

Step-by-step:

  1. Use []const u8 for strings.
  2. Format with std.fmt.allocPrint or std.fmt.bufPrint.
  3. Use std.mem for searching, splitting, trimming.
  4. Free allocated strings with defer.

Mini summary: Strings are []const u8. Use std.fmt and std.mem.

Lesson 9: Collections and Data Structures

Definition: Collections are containers for many values.

Why it is important: Collections help organize data.

Simple explanation: Like boxes for different kinds of items.

Real-life example: Banks use lists for transactions.

School example: Schools use maps for student grades.

Home example: Families use lists for shopping.

Nigerian example: Businesses use maps for product prices.

Illustration:

  Common std Collections:

  std.ArrayList(T)   → growable list
  std.StringHashMap(V) → key-value map
  std.AutoHashMap(K, V) → generic map
  std.Buffer         → dynamic string (older)

  Example with ArrayList:

  var list = std.ArrayList(i32).init(allocator);
  defer list.deinit();
  try list.append(1);
  try list.append(2);
  for (list.items) |item| {
      std.debug.print("{d}\n", .{item});
  }
  

Step-by-step:

  1. Choose the right collection.
  2. Initialize with an allocator.
  3. Use defer to deinit.
  4. Add, remove, and access items.

Mini summary: Collections like ArrayList and HashMap organize data. Use them with allocators.

Lesson 10: Organizing Code with @import

Definition: @import brings code from another file into your program.

Why it is important: It helps split large programs into small files.

Simple explanation: Like bringing a tool from another toolbox.

Real-life example: Banks split code into modules.

School example: Schools split subjects into books.

Home example: Families keep tools in different drawers.

Nigerian example: Businesses organize departments.

Illustration:

  Module Example:

  File: math.zig
    pub fn add(a: i32, b: i32) i32 {
        return a + b;
    }

  File: main.zig
    const math = @import("math.zig");
    pub fn main() void {
        std.debug.print("{d}\n", .{math.add(2, 3)});
    }
  

Step-by-step:

  1. Create a file with pub functions.
  2. In another file, use @import("file.zig").
  3. Use the imported functions with dot syntax.

Mini summary: @import splits code into files. Use pub to expose functions.

Lesson 11: Interfacing with C

Definition: Interfacing with C means calling C functions from Zig.

Why it is important: Zig can use existing C libraries.

Simple explanation: Like speaking another language to use a friend's tools.

Real-life example: Banks use C libraries for performance.

School example: Schools use C libraries for math.

Home example: Families use C libraries for games.

Nigerian example: Businesses use C libraries for speed.

Illustration:

  C Interop Example:

  const c = @cImport({
      @cInclude("stdio.h");
  });

  pub fn main() void {
      _ = c.printf("Hello from C!\n");
  }
  

Step-by-step:

  1. Use @cImport to import C headers.
  2. Call C functions with c.functionName.
  3. Link C libraries in build.zig if needed.

Mini summary: Zig can call C code with @cImport. This lets you reuse C libraries.

Lesson 12: Common Mistakes in Advanced Zig

Definition: Mistakes happen. Knowing them helps you avoid them.

Why it is important: Advanced code can hide subtle bugs.

Simple explanation: Like a small mistake in a big recipe.

Real-life example: Banks check their code carefully.

School example: Students check their projects.

Home example: Families double-check plans.

Nigerian example: Businesses test their tools.

Table of common mistakes:

MistakeWhat HappensHow to Fix
Forgetting to close filesResource leakUse defer file.close()
Not freeing stringsMemory leakUse defer allocator.free()
Wrong comptime usageCompile errorsUse carefully and test
Bad build.zig structureBuild failsFollow template
Missing test assertionsBugs not caughtWrite specific tests
Wrong C typesCrashesCheck C headers

Mini summary: Common mistakes include forgetting to close files and free strings. Always test and clean up.

Lesson 13: Best Practices for Advanced Zig

Definition: Best practices are good habits for clean, safe code.

Why it is important: Good habits prevent bugs and make code easy to read.

Simple explanation: Like keeping your tools sharp and organized.

Real-life example: Banks follow strict standards.

School example: Schools have writing guidelines.

Home example: Families keep the house tidy.

Nigerian example: Businesses use consistent procedures.

List of best practices:

  • Split code into modules with @import.
  • Write tests for every function.
  • Use defer right after opening resources.
  • Keep functions short and focused.
  • Use the standard library instead of rewriting.
  • Use comptime for constants and sizes.
  • Use generic functions for reusable code.
  • Use @typeInfo carefully and test.
  • Follow the C ABI when using C code.
  • Run zig fmt to keep code clean.

Mini summary: Best practices: modules, tests, defer, standard library, comptime, generics, zig fmt.

Lesson 14: Building a Multi-File Zig Project

Let’s build a complete multi-file project.

Step 1: Create a project folder.

Step 2: Create src/ for source files.

Step 3: Create src/main.zig with the entry point.

Step 4: Create src/math.zig with helper functions.

Step 5: Create src/data.zig with structs.

Step 6: Create build.zig.

Step 7: Write tests in each file.

Step 8: Run zig build run.

Illustration:

  Project Structure:

  myproject/
  ├── build.zig
  ├── src/
  │   ├── main.zig
  │   ├── math.zig
  │   └── data.zig
  └── README.md

  main.zig imports math.zig and data.zig.
  build.zig compiles everything together.
  

Mini summary: Multi-file projects organize code. Use @import and build.zig.

Lesson 15: Putting It All Together – Your Advanced Zig Toolkit

You now have a powerful toolkit for advanced Zig.

Your toolkit:

  • comptime metaprogramming: Generate code at compile time.
  • Generics: Write code for any type.
  • @typeInfo: Reflect on types.
  • Build system: Organize projects.
  • Unit tests: Verify code.
  • Standard library: Use ready tools.
  • Files, strings, collections: Work with data.
  • @import: Split into modules.
  • C interop: Use C libraries.

Illustration:

  Your Toolkit:
  +----------+  +----------+  +----------+
  | comptime |  | Generics |  |@typeInfo |
  +----------+  +----------+  +----------+
  +----------+  +----------+  +----------+
  | build.zig|  | Tests    |  | std      |
  +----------+  +----------+  +----------+
  +----------+  +----------+  +----------+
  | Files    |  | @import  |  | C interop|
  +----------+  +----------+  +----------+
  

Mini summary: Your advanced toolkit lets you build bigger, cleaner programs. Use it with confidence.

Key Vocabulary

WordSimple Definition
comptimeCode that runs at compile time.
MetaprogrammingWriting code that generates code.
GenericCode that works with many types.
@typeInfoBuilt-in function for type information.
Build systemTools for organizing and building projects.
build.zigThe build configuration file.
Unit testA small program that tests a piece of code.
Standard libraryReady-made code that comes with Zig.
stdThe Zig standard library.
ArrayListA growable list.
HashMapA key-value map.
@importBring code from another file.
ModuleA separate file of code.
C interopUsing C code from Zig.
@cImportImport C headers into Zig.

Important Concepts

  • comptime generates code: Runs before your program.
  • Generics work with any type: Write once, use many times.
  • @typeInfo reflects types: Write adaptive code.
  • Build system organizes projects: Use build.zig.
  • Tests verify code: Write them in test blocks.
  • Standard library saves time: Use std.
  • Files, strings, collections: Tools for real data.
  • @import splits code: Keep files small and clear.
  • C interop reuses libraries: Use @cImport.
  • Combine everything for big projects: Build real systems.

Step-by-step Explanations

How to set up a build.zig project step by step

  1. Create a folder for your project.
  2. Create src/main.zig.
  3. Create build.zig.
  4. Add the executable definition.
  5. Run zig build.
  6. Add a run step and use zig build run.

How to write a test step by step

  1. Import std.
  2. Write test "name" { ... }.
  3. Use try std.testing.expect(...).
  4. Run zig test file.zig.

How to read a file step by step

  1. Use std.fs.cwd().openFile(path, .{}).
  2. Use defer file.close().
  3. Read with file.readAll(&buffer).
  4. Use the data.

How to use ArrayList step by step

  1. Create with std.ArrayList(T).init(allocator).
  2. Use defer list.deinit().
  3. Add items with try list.append(x).
  4. Access with list.items.

How to use C interop step by step

  1. Use @cImport with @cInclude.
  2. Call C functions with c.functionName.
  3. Link libraries in build.zig if needed.

Real-life Examples

  • Banks: Use multi-file projects for banking systems.
  • Games: Use C interop for graphics libraries.
  • Schools: Use build systems for teaching projects.
  • Homes: Use std collections for home automation.
  • Businesses: Use tests to ensure quality.

Nigerian Examples

  • Banks: Nigerian banks use build systems for reliable software.
  • Startups: Nigerian startups use C interop for speed.
  • Schools: Students write tests for their projects.
  • Businesses: Businesses use std for file handling.
  • Freelancers: Freelancers use modules for reusable code.

Fun Examples Children Can Relate To

  • Games: Use tests to check game rules.
  • Stories: Split stories into chapters.
  • Calculators: Use generics for any number.
  • Collections: Track toys with ArrayList.
  • Toys: Sort toys with HashMap.

Everyday Examples

  • Shopping: Use ArrayList for shopping lists.
  • Homework: Write tests for math problems.
  • Family: Use modules for family rules.
  • Time: Use build steps to automate tasks.
  • Money: Use HashMap for expenses.

Parent Tips

  • Encourage your child to split code into modules.
  • Show them how to write tests.
  • Teach the importance of the build system.
  • Discuss how C interop reuses old code.
  • Praise them for clean, organized code.
  • Practice with small multi-file projects.
  • Read the Zig standard library docs together.
  • Keep sessions short and fun.
  • Let them teach you what they learned.
  • Support their learning journey.

Interesting Facts

  • Zig's build system is written in Zig.
  • Zig can compile C and C++ code.
  • comptime can compute nearly anything.
  • Zig's standard library is not huge, but it is powerful.
  • Zig's ArrayList is very common.
  • Zig tests run in the same language.
  • Zig supports cross-compilation easily.
  • Zig is used in production systems.

Did You Know?

  • Did you know that zig build handles everything?
  • Did you know that tests can be run automatically?
  • Did you know that Zig can read from any file?
  • Did you know that @import works like #include in C?
  • Did you know that @cImport can read C headers?
  • Did you know that comptime can loop?
  • Did you know that Zig's standard library is called std?
  • Did you know that Nigerian developers use Zig for performance?

Remember This

  • comptime generates code at compile time.
  • Generics work with any type.
  • @typeInfo gives type info.
  • build.zig organizes projects.
  • Tests verify code.
  • std provides many tools.
  • Files, strings, collections handle data.
  • @import splits code into modules.
  • @cImport lets you use C code.
  • Combine everything for big projects.

Common Mistakes

  • Forgetting to close files.
  • Not freeing strings.
  • Wrong comptime usage.
  • Bad build.zig structure.
  • Missing test assertions.
  • Wrong C types.
  • Not using defer.
  • Ignoring compiler errors.

Best Practices

  • Split code into modules.
  • Write tests for every function.
  • Use defer right after opening resources.
  • Keep functions short.
  • Use the standard library.
  • Use comptime for constants.
  • Use generics for reusable code.
  • Use @typeInfo carefully.
  • Follow the C ABI when using C code.
  • Run zig fmt often.

Illustrations and Diagrams

Project Structure

  myproject/
  ├── build.zig
  ├── src/
  │   ├── main.zig
  │   ├── math.zig
  │   └── data.zig
  └── README.md
  

Generic Function

  fn max(comptime T: type, a: T, b: T) T {
      return if (a > b) a else b;
  }
  

Test Workflow

  Write code
      |
      V
  Write test
      |
      V
  Run zig test
      |
      V
  Fix errors
      |
      V
  Pass ✅
  

File Handling

  openFile → defer close → read/write → use data
  

Your Learning Journey

  Module 1: Zig Basics
        |
        V
  Module 2: Memory & Errors
        |
        V
  Module 3: Advanced Features
        |
        V
  Module 4: Real Projects
        |
        V
  Zig Expert 🎉
  

Comparison Tables

comptime vs runtime

Featurecomptimeruntime
WhenCompile timeRun time
SpeedFastSlower
Best forConstants, genericsDynamic data

ArrayList vs Array

FeatureArrayListArray
SizeGrowsFixed
MemoryAllocatorStack/static
Best forUnknown countKnown count

@import vs @cImport

Feature@import@cImport
Used forZig filesC headers
LanguageZigC
PurposeModulesC interop

Test vs Debug Print

FeatureTestDebug Print
PurposeVerify codeShow data
RunsOn demandAlways
Use forQualityDebugging

Lesson Summaries

Lesson 1: Advanced comptime generates code at compile time.

Lesson 2: Generics work with any type.

Lesson 3: @typeInfo gives type information.

Lesson 4: build.zig organizes projects.

Lesson 5: Tests verify code with test blocks.

Lesson 6: std provides many useful tools.

Lesson 7: Files are read and written with std.fs.

Lesson 8: Strings use std.fmt and std.mem.

Lesson 9: Collections like ArrayList and HashMap store data.

Lesson 10: @import splits code into modules.

Lesson 11: C interop uses @cImport.

Lesson 12: Common mistakes: forgetting to close files, not freeing strings.

Lesson 13: Best practices: modules, tests, defer, std.

Lesson 14: Multi-file projects organize code well.

Lesson 15: Your advanced toolkit lets you build bigger programs.

End-of-Module Summary

Congratulations! You have finished Module Three of the Certified Zig Programming Expert course. You learned advanced comptime metaprogramming, generics, and compile-time reflection with @typeInfo. You learned about the Zig Build System and how to use build.zig. You learned to write unit tests, use the standard library, handle files, strings, and collections. You learned how to split code with @import and how to interface with C using @cImport. You learned common mistakes and best practices. Most importantly, you can now build bigger, cleaner, and more powerful Zig programs. In the next module, you will build real-world projects and earn your certification. Keep practising, and you will become a Zig expert!

Frequently Asked Questions

  1. What is comptime metaprogramming? Code that runs at compile time.
  2. What are generics? Code that works with any type.
  3. What is @typeInfo? A function that gives type information.
  4. What is build.zig? The configuration file for the Zig Build System.
  5. How do I write a test? Use test "name" { ... } and zig test.
  6. What is the standard library? Ready-made Zig code called std.
  7. How do I read a file? Use std.fs.cwd().openFile.
  8. What is ArrayList? A growable list in std.
  9. How do I split code? Use @import to bring in other files.
  10. How do I use C code? Use @cImport to import C headers.

Matching Exercises

Match the term to its meaning.

TermMeaning
1. comptimeA. Splits code into files
2. build.zigB. Compile-time code
3. TestC. Organizes project build
4. @importD. Verifies code
5. @cImportE. Imports C code

Answers: 1-B, 2-C, 3-D, 4-A, 5-E

Scenario-based Exercises

  1. Scenario: You want to write a function that works with any type. What do you do?
    Answer: Use a generic with comptime T: type.
  2. Scenario: You want to build a multi-file project. What do you use?
    Answer: build.zig and @import.
  3. Scenario: You want to test your code. What do you do?
    Answer: Write a test block and run zig test.
  4. Scenario: You want to read from a file. What do you use?
    Answer: std.fs.cwd().openFile.
  5. Scenario: You want to call C functions. What do you use?
    Answer: @cImport.

Group Activity

Title: “Build a Multi-File Zig Project Together”

Instructions: In groups of 3–4, create a small multi-file Zig project with at least three files: main.zig, math.zig, and data.zig. Write tests in each file. Create a build.zig file. One person writes main.zig, one person writes math.zig, one person writes data.zig, and one person writes build.zig. Run the project with zig build run. Share your project with the class.

Goal: Practice building a multi-file Zig project with tests and a build system.

Individual Activity

Task: Write a Zig program that:

  • Uses @import to bring in a helper file.
  • Uses std.ArrayList to store some numbers.
  • Uses a generic function to find the maximum.
  • Writes a test for the generic function.
  • Reads and writes a small file.

Hint: Start with small features and add one at a time.

Mini Project

Project: “My Multi-File Zig Tool”

Create a Zig project that:

  • Has a build.zig file.
  • Has main.zig as the entry point.
  • Has a math.zig module with a generic max function.
  • Has a data.zig module with a struct and ArrayList usage.
  • Reads a small text file and prints its contents.
  • Writes a summary file.
  • Has at least two tests.
  • Runs with zig build run.

Example output:

  Read 5 lines from input.txt
  Max value: 42
  Wrote summary to output.txt
  All tests passed ✅
  

Practical Assignment

Assignment: Build a small command-line tool in Zig. The tool should:

  1. Take a file name as input.
  2. Read the file line by line.
  3. Count the lines.
  4. Find the longest line.
  5. Print a summary.
  6. Write the summary to another file.
  7. Have at least three tests.
  8. Use build.zig to build and run.
  9. Use defer to close files.
  10. Handle errors with try and catch.

Submit: Your project folder with all .zig files and a screenshot of the output.

Key Takeaways

  • comptime generates code at compile time.
  • Generics work with any type.
  • @typeInfo gives type info.
  • build.zig organizes projects.
  • Tests verify code.
  • std provides many tools.
  • Files, strings, collections handle data.
  • @import splits code into modules.
  • @cImport lets you use C code.
  • Combine everything for big projects.

Classroom Discussion Questions

  1. What is comptime metaprogramming, and why is it useful?
  2. How do generics help you write less code?
  3. What does @typeInfo tell you about a type?
  4. Why is the Zig Build System useful?
  5. Why should you write tests?
  6. What can you find in the Zig Standard Library?
  7. How do you read and write files in Zig?
  8. How does @import help organize code?
  9. How does @cImport let you use C code?
  10. What did Ada learn from her big project?

Preparation for Module Four

In Module Four, we will build real-world projects and prepare for certification. We will cover:

  • Concurrency with threads and async patterns.
  • Networking and sockets in Zig.
  • Cross-compilation and Zig CC.
  • Performance optimization and benchmarking.
  • Packaging and publishing Zig libraries.
  • The certification project and exam preparation.

To prepare, make sure you have completed the practical assignment and have your multi-file project ready. Review the key vocabulary. Think about what kind of project you would like to build. Bring your curiosity!

See you in Module Four!


End of Module Three – Certified Zig Programming Expert

5

Module Four

Certified Zig Programming Expert – Module Four

Module Four: Real-World Projects and Certification – Becoming a Certified Zig Expert

“Certified Zig Programming Expert” – Master the language of modern systems programming

Module Introduction

Welcome to the final module, young Zig master! You have come a very long way. In Module One, you learned the basics of Zig. In Module Two, you learned memory management and error handling. In Module Three, you learned advanced features and the standard library.

Now, in Module Four, we will learn how to build real-world projects and prepare for your certification. This is where everything comes together. You will learn about concurrency (doing many things at once), networking (connecting computers), cross-compilation (building programs for other computers), performance optimization (making programs faster), and packaging your work.

Finally, you will complete your certification project. This project will show everything you have learned. By the end of this module, you will be a Certified Zig Programming Expert.

Let's begin!

Learning Objectives

After finishing this module, you will be able to:

  • Explain what concurrency is and why it matters.
  • Use threads in Zig to run tasks at the same time.
  • Understand the basics of networking and sockets.
  • Write a simple TCP server in Zig.
  • Cross-compile Zig programs for other systems.
  • Use Zig CC to compile C code.
  • Optimize Zig code for speed.
  • Package and publish Zig libraries.
  • Complete your certification project.
  • Plan your next steps as a Zig expert.

Warm-up Story: Emeka’s Chat Server

Emeka is 15 years old and lives in Port Harcourt. He has been learning Zig for several weeks and has built many small programs. Now he wants to build something bigger: a simple chat server that lets his friends send messages to each other over the internet.

Emeka started by learning about networking. He learned that a server is a program that listens for connections from clients. He learned about sockets, which are like doors that programs use to send and receive data.

Emeka also learned about concurrency. His chat server needed to handle many clients at the same time. He learned how to use threads, which are like workers who each handle one client.

He wrote a simple TCP server in Zig. He tested it with his friends. They could all connect and send messages. Emeka was very proud.

Next, Emeka learned about cross-compilation. He wanted his server to run on his father’s Linux computer, even though he was developing on Windows. Zig made this easy with a single command.

Finally, Emeka optimized his server for speed and packaged it as a library. He shared it online and received positive feedback. Emeka had become a real Zig developer.

Moral of the story: Real-world projects combine many Zig features. Concurrency, networking, cross-compilation, and optimization make your programs powerful and portable.

Main Lessons

Lesson 1: What is Concurrency?

Definition: Concurrency means doing many things at the same time.

Why it is important: It makes programs faster and more responsive.

Simple explanation: Imagine a chef cooking many dishes at once. That is concurrency.

Real-life example: A bank processes many transactions at once.

School example: A teacher handles many students' questions at once.

Home example: A family cooks, cleans, and watches TV at the same time.

Nigerian example: A market trader serves many customers at once.

Illustration:

  Concurrency:

  Without:                With:
  Task1 → Task2 → Task3   Task1 ─┐
                          Task2 ─┼→ All at once
                          Task3 ─┘
  

Mini summary: Concurrency is doing many things at the same time. It makes programs faster.

Lesson 2: Using Threads in Zig

Definition: A thread is a worker inside your program that runs code independently.

Why it is important: Threads let you run many tasks at the same time.

Simple explanation: Like having many workers in a shop, each serving a different customer.

Real-life example: Banks use threads for handling many transactions.

School example: Schools use threads for many class activities.

Home example: Families use threads for many chores.

Nigerian example: Businesses use threads for handling many orders.

Illustration:

  Thread Example:

  const std = @import("std");

  fn worker(id: u8) void {
      std.debug.print("Worker {d} is running\n", .{id});
  }

  pub fn main() !void {
      var threads: [4]std.Thread = undefined;
      for (&threads, 0..) |*t, i| {
          t.* = try std.Thread.spawn(.{}, worker, .{@as(u8, @intCast(i))});
      }
      for (&threads) |*t| t.join();
  }
  

Step-by-step:

  1. Write a function for each worker.
  2. Use std.Thread.spawn to start a thread.
  3. Store the thread handle.
  4. Use join to wait for the thread to finish.

Mini summary: Threads run tasks in parallel. Use std.Thread.spawn and join.

Lesson 3: Thread Safety and Mutexes

Definition: Thread safety means multiple threads can use shared data without breaking it. A mutex is a lock that ensures only one thread uses data at a time.

Why it is important: Without safety, threads can corrupt data.

Simple explanation: Like a single bathroom key that only one person can hold at a time.

Real-life example: Banks use locks for account balances.

School example: Schools use locks for shared resources.

Home example: Families use locks for shared appliances.

Nigerian example: Businesses use locks for shared inventory.

Illustration:

  Mutex Example:

  var counter: u32 = 0;
  var mutex: std.Thread.Mutex = .{};

  fn increment() void {
      mutex.lock();
      defer mutex.unlock();
      counter += 1;
  }
  

Step-by-step:

  1. Create a mutex with std.Thread.Mutex{}.
  2. Call mutex.lock() before using shared data.
  3. Use defer mutex.unlock().
  4. Access the shared data safely.

Mini summary: Mutexes protect shared data. Lock, use, unlock with defer.

Lesson 4: Introduction to Networking

Definition: Networking means connecting computers so they can send data to each other.

Why it is important: Networking enables the internet, chat, and file sharing.

Simple explanation: Like sending letters between houses in different cities.

Real-life example: Banks use networking for ATM transactions.

School example: Schools use networking for online classes.

Home example: Families use networking for Wi-Fi.

Nigerian example: Businesses use networking for online sales.

Illustration:

  Networking Basics:

  Client → Server → Client

  Client: asks for data
  Server: provides data
  Network: moves data between them
  

Mini summary: Networking connects computers so they can share data. Clients ask; servers provide.

Lesson 5: Sockets in Zig

Definition: A socket is an endpoint for sending and receiving data over a network.

Why it is important: Sockets let your program talk to other computers.

Simple explanation: Like a phone that lets you call another phone.

Real-life example: Banks use sockets for secure transactions.

School example: Schools use sockets for online learning.

Home example: Families use sockets for smart devices.

Nigerian example: Businesses use sockets for payments.

Illustration:

  Socket Basics:

  Server: listens on a port
     |
     V
  Client: connects to the server
     |
     V
  Data flows both ways
  

Mini summary: Sockets are endpoints for network communication. Servers listen; clients connect.

Lesson 6: A Simple TCP Server in Zig

Definition: A TCP server is a program that listens for clients and sends data reliably.

Why it is important: TCP servers power the internet.

Simple explanation: Like a shop that opens its doors for customers.

Real-life example: Banks run TCP servers for online banking.

School example: Schools run TCP servers for student portals.

Home example: Families run TCP servers for file sharing.

Nigerian example: Businesses run TCP servers for e-commerce.

Illustration:

  Simple TCP Server:

  const std = @import("std");

  pub fn main() !void {
      const address = try std.net.Address.parseIp("127.0.0.1", 8080);
      var server = try address.listen(.{});
      defer server.deinit();

      std.debug.print("Server listening on port 8080\n", .{});

      while (true) {
          const conn = try server.accept();
          defer conn.stream.close();
          try conn.stream.writeAll("Hello from Zig!\n");
      }
  }
  

Step-by-step:

  1. Parse the address with std.net.Address.parseIp.
  2. Listen with address.listen.
  3. Use defer server.deinit().
  4. Loop with accept to handle clients.
  5. Send data with writeAll.

Mini summary: TCP servers listen for clients and send data. Use std.net to build them.

Lesson 7: What is Cross-Compilation?

Definition: Cross-compilation means building a program for a different computer than the one you are using.

Why it is important: It lets your programs run on many systems.

Simple explanation: Like baking a cake for a friend in another city.

Real-life example: Banks build programs for Windows, Linux, and macOS.

School example: Schools build for different lab computers.

Home example: Families build for different devices.

Nigerian example: Businesses build for different customer systems.

Illustration:

  Cross-Compilation:

  Your Computer (Windows)
        |
        V
  Zig Compiler
        |
        +--> Linux executable
        |
        +--> macOS executable
        |
        +--> Windows executable
  

Step-by-step:

  1. Choose the target system.
  2. Use zig build-exe -target x86_64-linux.
  3. Copy the executable to the target system.
  4. Run it there.

Mini summary: Cross-compilation builds programs for other systems. Use -target with Zig.

Lesson 8: Using Zig CC

Definition: Zig CC is a C compiler built into Zig. It can compile C code.

Why it is important: It replaces other C compilers and supports cross-compilation.

Simple explanation: Like a universal translator for C code.

Real-life example: Banks compile C libraries with Zig CC.

School example: Schools teach C with Zig CC.

Home example: Families build small C tools.

Nigerian example: Businesses compile C code easily.

Illustration:

  Zig CC:

  zig cc -o myprogram myprogram.c

  This compiles C code using Zig's toolchain.

  Cross-compile:

  zig cc -target x86_64-linux -o myprogram myprogram.c
  

Step-by-step:

  1. Use zig cc instead of gcc or clang.
  2. Pass your C file.
  3. Add -target for cross-compilation.
  4. Run the output.

Mini summary: Zig CC compiles C code. It supports cross-compilation easily.

Lesson 9: Performance Optimization

Definition: Performance optimization means making your program run faster and use less memory.

Why it is important: Faster programs are better for users.

Simple explanation: Like finding a faster route to school.

Real-life example: Banks optimize for millions of transactions.

School example: Schools optimize for many students.

Home example: Families optimize routines.

Nigerian example: Businesses optimize for many customers.

Illustration:

  Optimization Tips:

  - Use ReleaseFast or ReleaseSmall
  - Avoid unnecessary allocations
  - Use comptime for constants
  - Choose the right data structures
  - Profile your code

  Build:

  zig build-exe -O ReleaseFast main.zig
  

Step-by-step:

  1. Measure your program's speed.
  2. Find slow parts.
  3. Apply optimizations.
  4. Measure again.
  5. Repeat until satisfied.

Mini summary: Optimize with release modes, fewer allocations, and the right structures.

Lesson 10: Benchmarking Your Code

Definition: Benchmarking means measuring how fast your program runs.

Why it is important: You cannot improve what you do not measure.

Simple explanation: Like timing how long it takes to run a race.

Real-life example: Banks benchmark their systems.

School example: Schools benchmark student progress.

Home example: Families time chores.

Nigerian example: Businesses benchmark delivery times.

Illustration:

  Benchmark Example:

  const std = @import("std");

  pub fn main() !void {
      var timer = try std.time.Timer.start();
      // Your code here
      const elapsed = timer.read();
      std.debug.print("Elapsed: {d} ns\n", .{elapsed});
  }
  

Step-by-step:

  1. Start a timer with std.time.Timer.start.
  2. Run your code.
  3. Read elapsed time with timer.read().
  4. Print the result.

Mini summary: Benchmarking measures speed. Use std.time.Timer to time code.

Lesson 11: Packaging and Publishing Zig Libraries

Definition: Packaging means preparing your code so others can use it. Publishing means sharing it online.

Why it is important: Sharing your work helps the community.

Simple explanation: Like wrapping a gift and giving it to a friend.

Real-life example: Companies publish libraries for others.

School example: Students share class projects.

Home example: Families share recipes.

Nigerian example: Businesses share open-source tools.

Illustration:

  Packaging Steps:

  1. Write clean code
  2. Add documentation
  3. Create build.zig
  4. Write tests
  5. Add a README
  6. Publish to GitHub or Zig package registry
  

Step-by-step:

  1. Organize your code into modules.
  2. Write clear comments.
  3. Add a build.zig.
  4. Write tests.
  5. Create a README.md.
  6. Push to GitHub or a package registry.

Mini summary: Package and publish your Zig code with docs, tests, and a README.

Lesson 12: Common Mistakes in Real Projects

Definition: Mistakes happen. Knowing them helps you avoid them.

Why it is important: Small mistakes can cause big problems.

Simple explanation: Like forgetting to lock the door.

Real-life example: Banks avoid bugs in transactions.

School example: Students check their projects.

Home example: Families double-check plans.

Nigerian example: Businesses test their software.

Table of common mistakes:

MistakeWhat HappensHow to Fix
Race conditionsData corruptionUse mutexes
Not closing socketsResource leakUse defer
Wrong targetProgram won't runCheck -target
No benchmarksSlow programUse std.time.Timer
Missing docsHard to useWrite a README
Ignoring warningsHidden bugsFix all warnings

Mini summary: Common mistakes: race conditions, unclosed sockets, wrong targets. Test and document.

Lesson 13: Best Practices for Real Projects

Definition: Best practices are good habits for professional code.

Why it is important: Good habits make code reliable and easy to maintain.

Simple explanation: Like keeping a clean workshop.

Real-life example: Banks follow strict standards.

School example: Students follow project guidelines.

Home example: Families keep things organized.

Nigerian example: Businesses use consistent procedures.

List of best practices:

  • Use threads carefully with mutexes.
  • Always close sockets and files with defer.
  • Write tests for everything.
  • Benchmark before optimizing.
  • Document your code.
  • Use zig fmt to keep code clean.
  • Follow the Zig style guide.
  • Package with build.zig.
  • Publish with clear READMEs.
  • Learn from the Zig community.

Mini summary: Best practices: safety, tests, benchmarks, docs, formatting, community.

Lesson 14: Preparing for the Certification Project

Your certification project brings everything together.

Project idea: Build a real-world application in Zig.

Steps:

  1. Choose a project (chat server, file tool, game, etc.).
  2. Plan the features.
  3. Organize into modules.
  4. Write clean, tested code.
  5. Add concurrency if needed.
  6. Add networking if needed.
  7. Cross-compile for other systems.
  8. Optimize for speed.
  9. Package with build.zig.
  10. Write a README and publish.

Illustration:

  Certification Project Flow:

  Idea
     |
     V
  Plan
     |
     V
  Code (modules, tests)
     |
     V
  Concurrency + Networking
     |
     V
  Cross-compile + Optimize
     |
     V
  Package + Publish
     |
     V
  Present 🎉
  

Mini summary: The certification project uses all skills. Plan carefully and build step by step.

Lesson 15: Putting It All Together – Your Certification and Beyond

You have learned so much. Let’s review.

Module One: Zig basics (variables, functions, structs, arrays).

Module Two: Memory and errors (pointers, allocators, optionals, error unions).

Module Three: Advanced features (comptime, generics, build system, std, C interop).

Module Four: Real projects (concurrency, networking, cross-compilation, optimization, packaging).

Next steps:

  • Complete your certification project.
  • Share your work online.
  • Contribute to open-source Zig projects.
  • Keep learning and improving.

Illustration:

  Certification
       |
       V
  Portfolio
       |
       V
  Share with others
       |
       V
  Help others learn
       |
       V
  Apply skills
       |
       V
  Zig Expert 🎉
  

Mini summary: Your certification opens doors. Keep growing, sharing, and building.

Key Vocabulary

WordSimple Definition
ConcurrencyDoing many things at once.
ThreadA worker that runs code.
MutexA lock for shared data.
NetworkingConnecting computers.
SocketAn endpoint for network data.
TCPA reliable network protocol.
ServerA program that listens for clients.
ClientA program that connects to a server.
Cross-compilationBuilding for another system.
Zig CCA C compiler built into Zig.
OptimizationMaking programs faster.
BenchmarkMeasuring speed.
PackagePreparing code to share.
PublishSharing code online.
Race conditionA bug from threads sharing data.

Important Concepts

  • Concurrency runs many tasks: Use threads.
  • Mutexes protect shared data: Lock and unlock.
  • Networking connects computers: Servers listen; clients connect.
  • Sockets move data: Use std.net.
  • TCP servers provide reliable data: Handle clients in a loop.
  • Cross-compilation builds for others: Use -target.
  • Zig CC compiles C: One tool for both languages.
  • Optimization makes programs fast: Use release modes.
  • Benchmarks measure speed: Use std.time.Timer.
  • Packaging shares your work: Include docs and tests.

Step-by-step Explanations

How to use threads step by step

  1. Write a function for the thread.
  2. Use std.Thread.spawn(.{}, function, args).
  3. Store the handle.
  4. Use join() to wait for completion.

How to protect shared data with a mutex step by step

  1. Declare a mutex with std.Thread.Mutex = .{}.
  2. Call mutex.lock() before use.
  3. Use defer mutex.unlock().
  4. Access shared data.

How to build a TCP server step by step

  1. Parse the address with std.net.Address.parseIp.
  2. Listen with address.listen.
  3. Use defer server.deinit().
  4. Accept clients in a loop.
  5. Send data with writeAll.

How to cross-compile step by step

  1. Choose the target (like x86_64-linux).
  2. Use zig build-exe -target x86_64-linux.
  3. Copy the executable to the target system.
  4. Run it there.

How to benchmark code step by step

  1. Start a timer with std.time.Timer.start().
  2. Run your code.
  3. Read timer.read().
  4. Print the elapsed time.

Real-life Examples

  • Banks: Use concurrency and networking for transactions.
  • Games: Use threads for animations and AI.
  • Schools: Use servers for student portals.
  • Homes: Use sockets for smart devices.
  • Businesses: Use cross-compilation for many systems.

Nigerian Examples

  • Banks: Nigerian banks use TCP servers for online banking.
  • Startups: Startups use threads for fast processing.
  • Schools: Schools teach concurrency with Zig.
  • Businesses: Businesses cross-compile for customer systems.
  • Freelancers: Freelancers package Zig libraries for clients.

Fun Examples Children Can Relate To

  • Games: Use threads for multiple players.
  • Chat: Build a simple chat server.
  • Stories: Use sockets to send stories between friends.
  • Toys: Package a toy library for friends.
  • Pets: Use concurrency to feed and walk pets.

Everyday Examples

  • Shopping: Use sockets for online shopping.
  • Homework: Use threads for many subjects.
  • Family: Use networking for video calls.
  • Time: Use benchmarks for faster routines.
  • Money: Use servers for mobile payments.

Parent Tips

  • Encourage your child to build real projects.
  • Teach them about concurrency and networking.
  • Help them cross-compile for other systems.
  • Show them how to benchmark and optimize.
  • Praise them for packaging and sharing.
  • Practice with small networking projects.
  • Read the Zig community forums together.
  • Keep sessions short and fun.
  • Let them teach you what they learned.
  • Support their certification journey.

Interesting Facts

  • Zig's threading API works on many systems.
  • Zig's networking uses cross-platform APIs.
  • Zig CC is used to build the Linux kernel.
  • Zig can cross-compile to WebAssembly.
  • Zig release modes can be 10x faster.
  • Zig has a package registry called Zigmod.
  • Zig libraries are used in production systems.
  • Zig is growing in popularity worldwide.

Did You Know?

  • Did you know that Zig can build for any Linux architecture?
  • Did you know that Zig threads are cross-platform?
  • Did you know that Zig CC replaces GCC and Clang?
  • Did you know that Zig's release modes are Debug, ReleaseSafe, ReleaseFast, and ReleaseSmall?
  • Did you know that Zig can build WebAssembly?
  • Did you know that Zig can cross-compile in a single command?
  • Did you know that Zig's std.net works on Windows and Linux?
  • Did you know that Nigerian developers contribute to Zig?

Remember This

  • Concurrency runs many tasks at once.
  • Threads are workers; mutexes protect data.
  • Networking connects computers.
  • Sockets move data; TCP is reliable.
  • Servers listen; clients connect.
  • Cross-compilation builds for other systems.
  • Zig CC compiles C code.
  • Optimization makes programs fast.
  • Benchmarks measure speed.
  • Packaging shares your work.

Common Mistakes

  • Race conditions.
  • Not closing sockets.
  • Wrong target.
  • No benchmarks.
  • Missing docs.
  • Ignoring warnings.
  • Not testing code.
  • Not using defer.

Best Practices

  • Use threads carefully with mutexes.
  • Always close sockets and files.
  • Write tests for everything.
  • Benchmark before optimizing.
  • Document your code.
  • Use zig fmt.
  • Follow the Zig style guide.
  • Package with build.zig.
  • Publish with clear READMEs.
  • Learn from the community.

Illustrations and Diagrams

Concurrency with Threads

  Without:                With:
  Task1 → Task2 → Task3   Task1 ─┐
                          Task2 ─┼→ All at once
                          Task3 ─┘
  

TCP Server

  Client → Server → Client

  Client: connects
  Server: listens
  Data: flows both ways
  

Cross-Compilation

  Windows → Zig → Linux, macOS, Windows
  

Optimization Process

  Measure → Find slow part → Optimize → Measure again
  

Your Learning Journey

  Module 1: Zig Basics
        |
        V
  Module 2: Memory & Errors
        |
        V
  Module 3: Advanced Features
        |
        V
  Module 4: Real Projects
        |
        V
  Zig Expert 🎉
  

Comparison Tables

Thread vs Process

FeatureThreadProcess
MemorySharedSeparate
SpeedFast to createSlow to create
SafetyNeeds locksIsolated

TCP vs UDP

FeatureTCPUDP
ReliabilityHighLow
SpeedSlowerFaster
Best forWeb, filesStreaming, games

Cross-compilation vs Native

FeatureCrossNative
Where builtOne systemTarget system
SpeedFastSlow
Best forMany targetsOne target

Release Modes

ModeSpeedSafety
DebugSlowHigh
ReleaseSafeMediumHigh
ReleaseFastFastMedium
ReleaseSmallSlowMedium

Lesson Summaries

Lesson 1: Concurrency does many things at once.

Lesson 2: Threads run tasks in parallel.

Lesson 3: Mutexes protect shared data.

Lesson 4: Networking connects computers.

Lesson 5: Sockets are endpoints for network data.

Lesson 6: TCP servers listen and send reliable data.

Lesson 7: Cross-compilation builds for other systems.

Lesson 8: Zig CC compiles C code.

Lesson 9: Optimization makes programs faster.

Lesson 10: Benchmarks measure speed.

Lesson 11: Packaging shares your work.

Lesson 12: Common mistakes: race conditions, unclosed sockets.

Lesson 13: Best practices: safety, tests, benchmarks, docs.

Lesson 14: The certification project uses all skills.

Lesson 15: Your certification opens doors.

End-of-Module Summary

Congratulations! You have finished Module Four and the entire Certified Zig Programming Expert course. You learned about concurrency and threads. You learned to use mutexes for safety. You learned about networking and sockets. You built a simple TCP server. You learned about cross-compilation and Zig CC. You learned to optimize and benchmark code. You learned to package and publish Zig libraries. You learned common mistakes and best practices. You prepared for and completed your certification project. Most importantly, you are now a Certified Zig Programming Expert. Keep building, keep sharing, and keep learning!

Frequently Asked Questions

  1. What is concurrency? Doing many things at the same time.
  2. What is a thread? A worker that runs code.
  3. What is a mutex? A lock for shared data.
  4. What is a socket? An endpoint for network data.
  5. What is TCP? A reliable network protocol.
  6. What is cross-compilation? Building for another system.
  7. What is Zig CC? A C compiler built into Zig.
  8. How do I optimize? Use release modes and fewer allocations.
  9. How do I benchmark? Use std.time.Timer.
  10. How do I package? Use build.zig and a README.

Matching Exercises

Match the term to its meaning.

TermMeaning
1. ThreadA. A lock for shared data
2. MutexB. An endpoint for network data
3. SocketC. A worker that runs code
4. Cross-compileD. Measuring speed
5. BenchmarkE. Building for another system

Answers: 1-C, 2-A, 3-B, 4-E, 5-D

Scenario-based Exercises

  1. Scenario: You want to run two tasks at the same time. What do you use?
    Answer: Threads.
  2. Scenario: Two threads need to update the same counter. What do you do?
    Answer: Use a mutex.
  3. Scenario: You want to build a chat server. What do you need?
    Answer: Sockets and TCP networking.
  4. Scenario: You want your program to run on Linux from Windows. What do you do?
    Answer: Cross-compile with -target.
  5. Scenario: You want to share your Zig library with friends. What do you do?
    Answer: Package with build.zig and publish on GitHub.

Group Activity

Title: “Build a Chat Server Together”

Instructions: In groups of 3–4, build a simple TCP chat server in Zig. Use threads to handle multiple clients. Use a mutex to protect shared data. Test with multiple terminals. One person writes the code, one person handles networking, one person handles concurrency, and one person writes tests. Share your server with the class.

Goal: Practice concurrency and networking together.

Individual Activity

Task: Write a Zig program that:

  • Spawns three threads.
  • Each thread prints a message.
  • Uses a mutex to protect a shared counter.
  • Uses std.time.Timer to measure total time.
  • Cross-compiles for Linux with -target x86_64-linux.

Hint: Start with a simple threaded program and add features.

Mini Project

Project: “My TCP Echo Server”

Create a TCP server in Zig that:

  • Listens on port 8080.
  • Accepts multiple clients using threads.
  • Echoes back any message received.
  • Uses a mutex to protect a shared client counter.
  • Logs each connection.
  • Has tests for the echo logic.
  • Cross-compiles for Linux.
  • Includes a README.

Example output:

  Server listening on port 8080
  Client 1 connected
  Received: Hello
  Client 2 connected
  Received: Hi
  

Practical Assignment

Assignment: Complete your certification project. Build a real-world Zig application that uses everything you have learned. Ideas include:

  1. A chat server with multiple clients.
  2. A file processing tool with concurrency.
  3. A simple game with networking.
  4. A command-line utility with many features.
  5. A library for others to use.

Requirements:

  • Use multiple modules with @import.
  • Write tests for your code.
  • Use concurrency or networking.
  • Cross-compile for at least one other system.
  • Optimize with a release mode.
  • Package with build.zig.
  • Write a clear README.
  • Publish on GitHub or a package registry.
  • Present your project to the class.

Submit: Your project folder, GitHub link, and a report on what you learned.

Key Takeaways

  • Concurrency runs many tasks at once.
  • Threads are workers; mutexes protect data.
  • Networking connects computers.
  • Sockets move data; TCP is reliable.
  • Servers listen; clients connect.
  • Cross-compilation builds for other systems.
  • Zig CC compiles C code.
  • Optimization makes programs fast.
  • Benchmarks measure speed.
  • Packaging shares your work.

Classroom Discussion Questions

  1. What is concurrency, and why is it useful?
  2. How do threads help programs run faster?
  3. Why do we need mutexes?
  4. How does networking connect computers?
  5. What is a socket, and how is it used?
  6. How does a TCP server work?
  7. Why is cross-compilation important?
  8. How does Zig CC help developers?
  9. How do you optimize and benchmark Zig code?
  10. What did Emeka learn from building his chat server?

Next Steps After Certification

Congratulations! You have completed the entire Certified Zig Programming Expert course. Here are some next steps you can take:

  • Practice: Keep building real projects.
  • Share: Publish your code on GitHub.
  • Contribute: Help open-source Zig projects.
  • Teach: Share your knowledge with others.
  • Explore: Learn more about Zig internals and the compiler.
  • Connect: Join the Zig community online.
  • Apply: Use Zig in school, home, or business.
  • Keep learning: Zig keeps improving.

Remember, this is just the beginning. You are now a Certified Zig Programming Expert. Keep building, keep learning, and keep growing!


End of Module Four – Certified Zig Programming Expert

🎉 Congratulations! You have completed the entire Certified Zig Programming Expert course! 🎉

🏆 Get Certified

🔒

Earn this certificate

Every lesson is already free to read. Sign up, pass the exam, and unlock Practice Tools plus a verified certificate with your name on it — ₦4,000/month.

🎓 Sign Up & Unlock for ₦4,000/month
🛠️ Practice Tools
Hands-on simulators & labs - subscription required.
→
🎯 Internship Tasks
Real-world tasks to build your portfolio - try them free for 7 days, no card required.
→