BUILD WITH
PURPOSE

// Simple, fast, reliable.

GO WAS BUILT FOR THE MODERN WEB.

Created at Google to solve their scaling problems, Go combines the performance of compiled languages with the ease of interpreted ones. It's the language behind Docker, Kubernetes, Terraform, and hundreds of cloud-native tools.

WHY GO?

Go is simple. The entire language can be learned in days. It compiles in seconds, produces single binary executables, and has built-in concurrency that makes parallel programming natural.

JOIN THE GOPHERS.

From web servers to DevOps tools, from APIs to distributed systems—Go powers the infrastructure of the internet. Master goroutines, channels, and the Go philosophy.

BEGIN YOUR JOURNEY →

// The Path to Mastery

12 lessons. Complete Go control.

LESSON 01

Introduction to Go

Install Go, write your first program, and understand the Go philosophy.

Beginner
LESSON 02

Variables & Types

Understand Go's type system, declarations, and zero values.

Beginner
LESSON 03

Functions

Write functions with multiple returns, named returns, and error handling.

Beginner
LESSON 04

Control Flow

Master if/else, switch statements, and loops in Go.

Beginner
LESSON 05

Arrays & Slices

Work with fixed and dynamic arrays, slicing, and appending.

Beginner
LESSON 06

Maps

Create and manipulate key-value data structures.

Intermediate
LESSON 07

Structs & Methods

Define custom types and attach methods to them.

Intermediate
LESSON 08

Interfaces

Understand Go's duck typing and polymorphism.

Intermediate
LESSON 09

Goroutines

Launch concurrent functions with lightweight threads.

Advanced
LESSON 10

Channels

Communicate between goroutines safely with channels.

Advanced
LESSON 11

Error Handling

Handle errors the Go way with explicit error returns.

Advanced
LESSON 12

Packages & Testing

Organize code and write tests with the testing package.

Advanced

// Why Go

Go was created in 2009 by Robert Griesemer, Rob Pike, and Ken Thompson at Google. They wanted a language that combined the performance of C++ with the simplicity of Python.

Go's philosophy emphasizes simplicity, readability, and efficiency. The language has only 25 keywords and a straightforward syntax. Yet it produces binaries that run as fast as compiled C code.

Go's built-in concurrency primitives—goroutines and channels—make it ideal for building scalable network services, microservices, and cloud-native applications. Companies like Google, Dropbox, Uber, and Twitch use Go for their most critical systems.

The future is Go. Own it.

// Tools & References

📖 Go Docs

Official Documentation

go.dev/doc

📦 Go Packages

Standard Library

pkg.go.dev

🐧 Go by Example

Hands-On Learning

gobyexample.com

🎮 Go Playground

Code Online

play.golang.org

// Introduction to Go

×

What is Go?

Go (also called Golang) is a compiled, statically typed programming language designed at Google by Robert Griesemer, Rob Pike, and Ken Thompson. It was first released in 2009 and version 1.0 in 2012.

Why Go?

  • Fast: Compiles in seconds, runs as fast as C
  • Simple: Only 25 keywords to learn
  • Concurrent: Built-in goroutines for parallel programming
  • Safe: Pointers but no pointer arithmetic
  • Standard Library: Powerful built-in packages
GO'S CREATORS: Go was created by the same people who invented Unix, C, and UTF-8. They wanted to solve problems they faced at Google with large-scale software development.

Installing Go

$ sudo apt update && sudo apt install golang-go # Or download from https://go.dev/dl/

Verify Installation

$ go version go1.21.0 linux/amd64

Your First Go Program

// hello.go package main import "fmt" func main() { fmt.Println("Hello, World!") }

Run Your Program

$ go run hello.go Hello, World!

Go Workspace

Go uses a specific directory structure:

$ mkdir -p ~/go/src/hello && cd ~/go/src/hello

Your code goes in src/, compiled binaries go to bin/

Go Commands

$ go build hello.go # Compile $ go run hello.go # Compile and run $ go fmt hello.go # Format code $ go get hello.go # Get dependencies

Quiz

1. Go was created at _____ (company).

2. How many keywords does Go have?

3. What command runs a Go program?

// Variables & Types

×

Variable Declaration

Go has several ways to declare variables:

// Explicit type var name string = "Alice" var age int = 25 // Type inference var city = "London" // Short declaration (inside functions) country := "UK" count := 10

Basic Types

bool // true or false string // "hello" int // 1, 42, -100 int8 // -128 to 127 int16 // -32768 to 32767 int32 // -2B to 2B int64 // very large numbers uint // positive integers float32 // 32-bit float float64 // 64-bit float (default) complex64 // complex numbers byte // alias for uint8 rune // alias for int32 (Unicode)

Zero Values

Uninitialized variables get zero values:

var i int // 0 var f float64 // 0 var s string // "" var b bool // false

Constants

const Pi = 3.14159 const ( StatusOK = 200 StatusNotFound = 404 )

Type Conversion

var i int = 42 var f float64 = float64(i) var s string = "123" var n int, _ = strconv.Atoi(s)

Quiz

1. What is the zero value of int?

2. What keyword declares a constant?

3. What operator declares a variable with type inference?

// Functions

×

Basic Function

func greet(name string) string { return "Hello, " + name }

Multiple Return Values

One of Go's most powerful features:

func divide(a, b float64) (float64, error) { if b == 0 { return 0, fmt.Errorf("cannot divide by zero") } return a / b, nil } // Usage result, err := divide(10, 2) if err != nil { fmt.Println(err) } else { fmt.Println(result) }

Named Returns

func split(sum int) (x, y int) { x = sum * 4 / 9 y = sum - x return // naked return }

Variadic Functions

func sum(nums ...int) int { total := 0 for _, n := range nums { total += n } return total } fmt.Println(sum(1, 2, 3)) // 6 fmt.Println(sum(1, 2)) // 3

Functions as Values

func apply(fn func(int) int, val int) int { return fn(val) } square := func(x int) int { return x * x } fmt.Println(apply(square, 5)) // 25

Quiz

1. How many values can a function return?

2. What does ...int mean in a parameter?

// Control Flow

×

If Statement

if x > 0 { fmt.Println("positive") } else if x < 0 { fmt.Println("negative") } else { fmt.Println("zero") } // Variables in condition if v := math.Pow(2, 3); v > 5 { fmt.Println("greater than 5") }

Switch Statement

switch day { case "Monday": fmt.Println("Start of week") case "Friday": fmt.Println("TGIF!") default: fmt.Println("Regular day") } // Switch without expression switch { case age < 18: fmt.Println("minor") case age >= 18 && age < 65: fmt.Println("adult") default: fmt.Println("senior") }

For Loop

// Classic for for i := 0; i < 10; i++ { fmt.Println(i) } // While-style (no init/post) sum := 1 for ; sum < 1000; { sum += sum } // Infinite loop for { if done { break } } // Range for i, v := range []int{1, 2, 3} { fmt.Println(i, v) }

Break & Continue

for i := 0; i < 10; i++ { if i == 5 { break // Exit loop } if i%2 == 0 { continue // Skip even numbers } fmt.Println(i) }

Quiz

1. What keyword skips to the next iteration?

2. What is the only loop keyword in Go?

// Arrays & Slices

×

Arrays

Fixed-size sequences:

var arr [5]int // [0 0 0 0 0] arr[0] = 1 // Initialize primes := [6]int{2, 3, 5, 7, 11, 13} // Let compiler count arr := [...]int{1, 2, 3}

Slices

Dynamic-size views into arrays:

// Create slice slice := []int{1, 2, 3, 4, 5} // From array arr := [5]int{1, 2, 3, 4, 5} s := arr[1:4] // [2, 3, 4] // make function s := make([]int, 3, 5) // length 3, capacity 5

Slice Operations

// append - add elements slice = append(slice, 6, 7) // len - number of elements fmt.Println(len(slice)) // 5 // cap - underlying array size fmt.Println(cap(slice)) // copy - duplicate slice dst := make([]int, len(src)) copy(dst, src)

Iterating Slices

// Index and value for i, v := range slice { fmt.Printf("%d: %d\n", i, v) } // Just value for _, v := range slice { fmt.Println(v) }

Quiz

1. What function adds elements to a slice?

2. What is the underlying data structure of a slice?

// Maps

×

Creating Maps

// Create with make ages := make(map[string]int) ages["Alice"] = 30 ages["Bob"] = 25 // Initialize directly prices := map[string]float64{ "apple": 0.99, "banana": 0.59, }

Map Operations

// Access (returns zero if not found) age := ages["Alice"] // Check if key exists age, ok := ages["Charlie"] if !ok { "Charlie not found" } // Delete delete(ages, "Bob") // Length len(ages)

Iterating Maps

for key, value := range ages { fmt.Printf("%s: %d\n", key, value) } // Just keys for key := range ages { fmt.Println(key) }

Quiz

1. How do you check if a key exists in a map?

2. What function deletes a map entry?

// Structs & Methods

×

Structs

type Person struct { Name string Age int Email string } // Create instance p1 := Person{ Name: "Alice", Age: 30, Email: "alice@example.com", } p2 := Person{"Bob", 25, ""} // Zero value struct var p3 Person // {"" 0 ""}

Methods

Functions attached to structs:

func (p Person) Greet() string { return "Hello, I'm " + p.Name } // Pointer method (can modify) func (p *Person) Birthday() { p.Age++ }

Embedding (Inheritance)

type Employee struct { Person // Embedded Company string Salary int } e := Employee{ Person: Person{Name: "Alice", Age: 30}, Company: "Acme", } fmt.Println(e.Name) // Alice (promoted) fmt.Println(e.Person.Name) // Alice

Quiz

1. What keyword defines a custom type?

2. What do you use to modify a struct from a method?

// Interfaces

×

Defining Interfaces

type Writer interface { Write([]byte) (int, error) } type Reader interface { Read([]byte) (int, error) } // Combined interface type ReadWriter interface { Reader Writer }

Implementing Interfaces

Implicitly - any type with the right methods implements the interface:

type Counter struct { Count int } // This makes Counter implement fmt.Stringer func (c Counter) String() string { return fmt.Sprintf("Count: %d", c.Count) }

Empty Interface

// interface{} accepts any type func PrintAny(v interface{}) { fmt.Println(v) } PrintAny(42) PrintAny("hello") PrintAny([]int{1, 2, 3})

Type Assertions

var i interface{} = "hello" // Type assertion s := i.(string) fmt.Println(s) // Safe type assertion s, ok := i.(string) if ok { fmt.Println(s) }

Quiz

1. How do you implement an interface in Go?

2. What is an empty interface called?

// Goroutines

×

What is a Goroutine?

A goroutine is a lightweight thread managed by the Go runtime. They are cheaper than OS threads - you can have thousands running simultaneously.

Starting a Goroutine

func say(msg string) { for i := 0; i < 3; i++ { fmt.Println(msg) } } // Regular call say("hello") // Goroutine - runs concurrently go say("world")

Waiting for Goroutines

import "sync" var wg sync.WaitGroup for i := 0; i < 5; i++ { wg.Add(1) go func(n int) { defer wg.Done() fmt.Println(n) }(i) } wg.Wait() // Block until all done

Channels

// Create channel ch := make(chan int) // Send ch <- 42 // Receive value := <-ch

Buffered Channels

// Channel with buffer of 10 ch := make(chan int, 10) // Won't block until buffer full ch <- 1 ch <- 2

Quiz

1. What keyword starts a goroutine?

2. What waits for goroutines to finish?

// Channels

×

Channel Basics

// Communication between goroutines func sum(nums []int, result chan<- int) { total := 0 for _, n := range nums { total += n } result <- total // Send to channel } ch := make(chan int) go sum([]int{1, 2, 3}, ch) result := <-ch // Receive from channel

Close Channel

// Sender closes when done ch := make(chan int) go func() { for i := 0; i < 5; i++ { ch <- i } close(ch) }() // Receiver checks if open for { v, ok := <-ch if !ok { break } fmt.Println(v) }

Select Statement

Wait on multiple channels:

select { case msg := <-ch1: fmt.Println("Received from ch1:", msg) case msg := <-ch2: fmt.Println("Received from ch2:", msg) case <-time.After(time.Second): fmt.Println("Timeout") default: fmt.Println("No message ready") }

Directional Channels

// send-only channel func produce(out chan<- int) { for i := 0; i < 5; i++ { out <- i } close(out) } // receive-only channel func consume(in <-chan int) { for n := range in { fmt.Println(n) } }

Quiz

1. What statement waits on multiple channels?

2. How do you iterate over a channel?

// Error Handling

×

Error Interface

type error interface { Error() string } // Using errors.New import "errors" var ErrNotFound = errors.New("not found") // Using fmt.Errorf return nil, fmt.Errorf("user %d not found", id)

Handling Errors

// Always check errors result, err := doSomething() if err != nil { // Handle error return err } // Common patterns if err != nil { if errors.Is(err, ErrNotFound) { // Specific error } return err }

Custom Errors

type ValidationError struct { Field string Message string } func (e ValidationError) Error() string { return e.Field + ": " + e.Message }

Defer

// Execute after function returns func readFile(name string) { f, err := os.Open(name) if err != nil { return err } defer f.Close() // Runs before return // Work with file }

Panic & Recover

func safeCall() { defer func() { if r := recover(); r != nil { fmt.Println("Recovered:", r) } }() // Panic will be caught panic("something bad") }

Quiz

1. How do you create a new error?

2. What runs before a function returns?

// Packages & Testing

×

Packages

// File 1 package mathutil func Add(a, b int) int { return a + b } // File 2 package mathutil func Subtract(a, b int) int { return a - b }

Imports

import ( "fmt" "mathutil" // local package "strings" myalias "some/package" // alias ) fmt.Println(mathutil.Add(2, 3))

Init Function

var config string func init() { // Runs before main config = loadConfig() }

Writing Tests

// add.go package mathutil func Add(a, b int) int { return a + b } // add_test.go package mathutil import "testing" func TestAdd(t *testing.T) { result := Add(2, 3) if result != 5 { t.Fail("expected 5") } }

Running Tests

$ go test ./... # Run all tests $ go test -v # Verbose output $ go test -run TestAdd # Run specific test $ go test -bench . # Run benchmarks

Benchmarks

func BenchmarkAdd(b *testing.B) { for i := 0; i < b.N; i++ { Add(1, 2) } }

Quiz

1. What file contains tests?

2. What runs before main()?