# 🐹 Cheatsheet: Intermediate Go: Build Concurrent Backend Services

> This cheatsheet is part of the paid section. Sign in and purchase the course to view the full content.

Scope: concurrency foundations, HTTP service + data access, and shipping with gRPC, profiling, and containers.

---

## Module 1: Concurrency as the Spine

### 1.1 Types, Interfaces, Errors

| Concept | Rule of thumb |
| --- | --- |
| Value semantics | Struct passed by value = copy. Mutate via pointer `*T` receiver only when needed |
| Interface size | Small (1-3 methods). Define at the consumer, not the producer |
| Nil interface trap | `var e error = (*MyErr)(nil)` is non-nil; return explicit `nil` |
| Error wrapping | `fmt.Errorf("...: %w", err)` keeps the chain |
| Error inspection | `errors.Is` for sentinels, `errors.As` for typed errors |
| Panic | Only for unrecoverable programmer bugs, never for control flow |

```go
var ErrNotFound = errors.New("not found")

if errors.Is(err, ErrNotFound) { /* sentinel match */ }
var pe *PathError
if errors.As(err, &pe) { /* typed match */ }
```

> [!TIP]
> Wrap with `%w` and add context at each layer. Unwrap down to the sentinel only at the boundary that decides behavior.

### 1.2 Goroutines, Channels, Context

| Need | Use |
| --- | --- |
| Hand off data / ownership | Channel |
| Guard state that stays put | `sync.Mutex` / `sync.RWMutex` |
| Request deadline + cancellation | `context.Context` |
| Wait for N goroutines | `sync.WaitGroup` |
| One-time init | `sync.Once` |

Rules:
- Every goroutine needs an exit path. No fire-and-forget.
- Pass `ctx` as the first parameter; never store it in a struct.
- `select` on `ctx.Done()` to respect cancellation.
- Close a channel from the sender only. Receivers never close.
- Buffered channel = bounded queue; size it deliberately.

```go
select {
case <-ctx.Done():
    return ctx.Err()
case v := <-ch:
    handle(v)
}
```

### 1.3 Bounded Fan-Out with errgroup
