191 Patterns from Go Programming (2nd ed., 2024)
191 Patterns from Go Programming (2nd ed., 2024)
This chapter extracts topics from the 2024 second edition arc: debugging, time handling, CLI work, files/systems, SQL, HTTP server/client, concurrency, testing, tooling, and cloud.
What This Adds to Our Book
- Stronger bridge from core syntax to practical operations.
- Dedicated narrative on “time as a correctness boundary”.
- Better pairing of HTTP server and HTTP client behavior in one lifecycle.
- Cloud-readiness framing: configuration, graceful shutdown, observability, packaging.
Learning Architecture
core language -> application boundary (CLI/API) -> state boundary (DB/files) -> operational boundary (timeouts, cloud, tools)
Deep Integration Example: API + CLI + DB Boundary
package app
import (
"context"
"database/sql"
"encoding/json"
"errors"
"fmt"
"net/http"
"os"
"time"
)
var ErrNotFound = errors.New("not found")
type User struct {
ID int64 `json:"id"`
Email string `json:"email"`
}
type Store struct{ DB *sql.DB }
func (s Store) GetUser(ctx context.Context, id int64) (User, error) {
ctx, cancel := context.WithTimeout(ctx, 2*time.Second)
defer cancel()
var u User
err := s.DB.QueryRowContext(ctx, `SELECT id, email FROM users WHERE id=$1`, id).Scan(&u.ID, &u.Email)
if errors.Is(err, sql.ErrNoRows) {
return User{}, ErrNotFound
}
if err != nil {
return User{}, fmt.Errorf("query user %d: %w", id, err)
}
return u, nil
}
type API struct{ Store Store }
func (a API) GetUserHandler(w http.ResponseWriter, r *http.Request) {
ctx, cancel := context.WithTimeout(r.Context(), 3*time.Second)
defer cancel()
user, err := a.Store.GetUser(ctx, 42)
if errors.Is(err, ErrNotFound) {
http.Error(w, "not found", http.StatusNotFound)
return
}
if err != nil {
http.Error(w, "internal error", http.StatusInternalServerError)
return
}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(user)
}
func ReadEnvDuration(key string, fallback time.Duration) time.Duration {
v := os.Getenv(key)
if v == "" {
return fallback
}
d, err := time.ParseDuration(v)
if err != nil {
return fallback
}
return d
}Why This Matters
The example demonstrates a full chain from request boundary to storage boundary with explicit timeouts and typed errors. That is the practical center of modern Go backend development.
Curriculum Upgrades Recommended
- Add a dedicated chapter linking debugging, benchmarking, and production incident triage.
- Expand
timechapter with deadline budgeting patterns for server+client+DB together. - Add side-by-side chapter pair:
net/httpserver correctness andhttp.Clientresilience. - Add cloud deployment chapter emphasizing runtime config contracts and shutdown policy.