main.goCourse

Go

A typed name, then a struct you can call, then the rules for a zero value, a nil map, a pointer receiver, and an interface.

A cup label is three typed values
  1. namestringlatte
  2. centsint450
  3. readybooltrue

6 lessons, in orderFree to read

Syllabus

Basics

The types, explained, then an object you can name and call.

  1. A Go name has a type. name is a string, cents is an int, and ready is a bool. The program prints latte $4.50 ready.

    package main
    
    import "fmt"
    
    func main() {
        var name string = "latte"
        var cents int = 450
        var ready bool = true
        var status string = "sold out"
        if ready {
            status = "ready"
        }
        fmt.Printf("%s $%d.%02d %s\n", name, cents/100, cents%100, status)
    }
    latte $4.50 ready
    
  2. A struct groups named fields, and a method is a function on that struct. Item holds a drink and a price in cents, and Label prints latte $4.50.

    Builds on lesson 1.

    package main
    
    import "fmt"
    
    type Item struct {
        Name  string
        Cents int
    }
    
    func (it Item) Label() string {
        return fmt.Sprintf("%s $%d.%02d", it.Name, it.Cents/100, it.Cents%100)
    }
    
    func main() {
        latte := Item{Name: "latte", Cents: 450}
        fmt.Println(latte.Label())
    }
    latte $4.50
    

Practice

A rule that prevents a bug, then a program that uses the object.

  1. A var with no value is not empty of meaning. A blank order has an empty name and 0 cents. The program prints "" $0.00.

    Builds on lessons 1 through 2.

    package main
    
    import "fmt"
    
    func main() {
        var name string
        var cents int
        fmt.Printf("%q $%d.%02d\n", name, cents/100, cents%100)
    }
    "" $0.00
    
  2. A map has to be made before a write. map[string]int{} makes a menu. The program stores 450 under latte and prints 450.

    Builds on lessons 1 through 3.

    package main
    
    import "fmt"
    
    func main() {
        menu := map[string]int{}
        menu["latte"] = 450
        fmt.Println(menu["latte"])
    }
    450
    

Further

One more idea, then a program that puts the pieces together.

  1. A method with a pointer receiver changes the struct the caller holds. AddTip adds 20 percent to a $4.50 bill, and the program prints $5.40.

    Builds on lessons 1 through 4.

    package main
    
    import "fmt"
    
    type Bill struct {
        cents int
    }
    
    func (b *Bill) AddTip(percent int) {
        b.cents = b.cents + b.cents*percent/100
    }
    
    func main() {
        b := &Bill{cents: 450}
        b.AddTip(20)
        fmt.Printf("$%d.%02d\n", b.cents/100, b.cents%100)
    }
    $5.40
    
  2. An interface names the methods a function needs. Labeller asks for Label, Item has Label, and show prints latte $4.50.

    Builds on lessons 1 through 5.

    package main
    
    import "fmt"
    
    type Item struct {
        Name  string
        Cents int
    }
    
    func (it Item) Label() string {
        return fmt.Sprintf("%s $%d.%02d", it.Name, it.Cents/100, it.Cents%100)
    }
    
    type Labeller interface {
        Label() string
    }
    
    func show(l Labeller) {
        fmt.Println(l.Label())
    }
    
    func main() {
        show(Item{Name: "latte", Cents: 450})
    }
    latte $4.50
    

Readings

Shorter pieces in the same language. Any order is fine once the lessons feel familiar.

  1. Context: cancel the parent, the children hear it 3 min

    GoByte Skills #3: One cancel() at the root closes Done on every context below it, and closing a channel wakes every waiter at once. Context is a tree, not a kill switch. Also: why a dropped stop() leaks.

  2. errors.Is: wrap it, keep the cause 2 min

    GoByte Skills #2: %v prints the exact same message and quietly drops the chain. %w keeps it, and errors.Is walks it link by link, so the cause survives every layer of context.

  3. Go channels: the queue that says no 3 min

    GoByte Skills #1: A buffered channel is a bounded queue. When it is full, the send parks until there is room, so the slow consumer sets the pace. Backpressure in one argument to make(), plus the exact order a real run prints.