Skip to content

Chapter 09: Functions ​

"Don't repeat yourself (DRY)."

If you copy-paste the same code 3 times, you are creating a maintenance nightmare. We pack logic into reusable machines called Functions.

9.1 The Metaphor: The Meat Grinder ​

A function is like a meat grinder:

  1. Top (Arguments): You throw in raw ingredients (Numbers, Strings).
  2. Gears (Body): The machine processes them (Calculates, Formats).
  3. Bottom (Return): Processed meat comes out (Result).

9.2 Anatomy of a Function ​

go
// Keyword   Name      Inputs (Type)      Outputs (Type)
func         Add       (a int, b int)     int {
    return a + b
}

9.3 Multiple Returns ​

A Go function can return multiple values. Other languages also support this feature. Usually, we return (Result, Error).

go
func Divide(a, b int) (int, error) {
    if b == 0 {
        return 0, fmt.Errorf("cannot divide by zero")
    }
    return a / b, nil
}

The "Guard Clause" Pattern: Notice how we check for errors first and return early? This keeps our code clean (no nested else hell).

9.3b Idiomatic Naming: Getters ​

In Java, you might write GetName(). In Go, we just say Name().

  • Bad: GetOwner(), GetPrice(), GetAll()
  • Good: Owner(), Price(), All()

If a function fetches something remotely or expensively, we usually just verb it directly (Fetch(), Find()). If it's a simple property access, drop the Get.

9.4 Practice: Interaction & Validation ​

In this lesson, we build a function that accepts User Input, validates it (checks for errors), and returns a safe result.

go
package main

import (
	"html/template"
	"log"
	"net/http"
	"strings"
	"sync"
)

// Lesson 4: Interaction
// Goal: Accept user input via Forms and Validate it (The Quality Gate).

type Book struct {
	Title  string
	Author string
}

var booksMu sync.Mutex

var books = []Book{
	{"The Go Gopher", "Rob Pike"},
}

const htmlTmpl = `
<!DOCTYPE html>
<head><link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet"></head>
<body class="container py-5">
    <h1>📚 The Gopher Shop</h1>

    <!-- FORM -->
    <form action="/add" method="POST" class="mb-4 row g-3">
        <div class="col-auto"><input type="text" name="title" class="form-control" placeholder="Title"></div>
        <div class="col-auto"><input type="text" name="author" class="form-control" placeholder="Author"></div>
        <div class="col-auto"><button type="submit" class="btn btn-primary">Add Book</button></div>
    </form>

    <!-- LIST -->
    <ul class="list-group">
    {{range .}}
        <li class="list-group-item">{{.Title}} ({{.Author}})</li>
    {{end}}
    </ul>
</body>
</html>
`

func main() {
	tmpl := template.Must(template.New("index").Parse(htmlTmpl))

	// GET: Show Page
	http.HandleFunc("GET /", func(w http.ResponseWriter, r *http.Request) {
		booksMu.Lock()
		snapshot := append([]Book(nil), books...)
		booksMu.Unlock()
		if err := tmpl.Execute(w, snapshot); err != nil {
			log.Print(err)
		}
	})

	// POST: Handle Data
	http.HandleFunc("POST /add", func(w http.ResponseWriter, r *http.Request) {
		r.Body = http.MaxBytesReader(w, r.Body, 64<<10)
		if err := r.ParseForm(); err != nil {
			http.Error(w, "Invalid form", http.StatusBadRequest)
			return
		}
		title := strings.TrimSpace(r.PostForm.Get("title"))
		author := strings.TrimSpace(r.PostForm.Get("author"))

		// 🛡️ THE QUALITY GATE (Validation)
		// Why? Never trust user input. It could be empty, malicious, or wrong.
		// We reject bad data BEFORE it touches our database.
		if title == "" || author == "" {
			http.Error(w, "Title and author are required!", http.StatusBadRequest)
			return
		}

		// If good, add to shelf
		booksMu.Lock()
		books = append(books, Book{title, author})
		booksMu.Unlock()
		http.Redirect(w, r, "/", http.StatusSeeOther)
	})

	log.Println("🚀 Shop v4 running on http://localhost:8080")
	log.Fatal(http.ListenAndServe("127.0.0.1:8080", nil))
}
🎓 Knowledge Check: What happens if we don't validate user input?

Answer: The "Quality Gate" stays open to garbage! Users could submit empty books, negative prices, or malicious code. Validation protects your database.

4 The Visual Signal (The Blender) ​

Concept: Input -> Process -> Output. Signal: A Kitchen Blender. You put fruit in (Parameters), hit the button (Execute body), and get juice out (Return Values).

The form lesson runs handlers concurrently. Its sync.Mutex protects both copying and appending the shared slice; template rendering uses the snapshot after unlocking. The GET / and POST /add patterns restrict methods. MaxBytesReader limits input before ParseForm; form parsing can fail and is checked. These are the minimal HTTP safety prerequisites, developed further in Middle chapter 8. The lesson is a local demo without user accounts or authorization.

Released under the MIT License.