# Library Replacement Guide — Go

## When to Consider

All three conditions must hold:
1. **Profiling evidence**: Library accounts for >15% of cumtime
2. **Plateau evidence**: Domain agent tried to reduce calls, cache results — still plateaued
3. **Narrow usage surface**: Codebase uses a small fraction of the library's API

## Common Replacements

| Library | Use case | stdlib alternative |
|---------|----------|-------------------|
| `encoding/json` (reflect-based) | JSON marshaling | Code-generated: `easyjson`, `sonic`, `go-json` |
| `fmt.Sprintf` | String formatting | `strconv` + `strings.Builder` |
| `regexp` (for simple patterns) | Pattern matching | `strings.Contains/HasPrefix/Cut` |
| `net/http` (full server) | Simple routing | Direct `http.HandlerFunc` (avoid framework overhead) |
| `pkg/errors` | Error wrapping | `fmt.Errorf("%w", err)` (Go 1.13+) |
| `logrus/zap` (for simple cases) | Logging | `log/slog` (Go 1.21+) |
| `go-yaml` | YAML parsing | Consider if JSON or TOML would work instead |
| CGo library | C bindings | Pure Go alternative (check awesome-go) |
| `net/http` (high concurrency) | HTTP server | `cloudwego/netpoll` (epoll-based, minimal GC) or `tidwall/evio` (event loop) |
| `net` (DNS resolution) | DNS lookup | Custom resolver with caching (Go doesn't cache DNS by default) |
| Manual TLS config | TLS performance | Session tickets + ECDSA certs + AES-GCM (58% faster in Go 1.25) |

## Assessment Process

### Step 1: Audit usage surface
```bash
# What does the codebase import from the library?
grep -rn 'import.*"library"' --include='*.go' . | grep -v vendor
grep -rn 'library\.' --include='*.go' . | grep -v _test.go | grep -v vendor | sort -u
```

### Step 2: Classify each usage
- Can stdlib handle this?
- Does the library provide safety guarantees the replacement must maintain?
- Are there edge cases the library handles that a simple replacement would miss?

### Step 3: Implement replacement
- One function at a time
- Benchmark each replacement independently
- Verify correctness with existing tests

### Step 4: Verify
```bash
go test ./...
go test -race -short ./...
go vet ./...
benchstat old.txt new.txt
```

## encoding/json Replacement (most common)

`encoding/json` uses reflect and allocates heavily. For hot paths:

### Option A: Code-generated marshaler
```bash
# Install easyjson
go install github.com/mailru/easyjson/...@latest

# Generate marshalers
easyjson -all pkg/model/types.go
```

### Option B: Manual marshaling for critical paths
```go
// Instead of json.Marshal(obj), write directly:
func (o *Obj) MarshalJSON() ([]byte, error) {
    var buf bytes.Buffer
    buf.WriteString(`{"name":"`)
    buf.WriteString(o.Name)
    buf.WriteString(`","count":`)
    buf.WriteString(strconv.Itoa(o.Count))
    buf.WriteByte('}')
    return buf.Bytes(), nil
}
```

### Option C: Use a faster JSON library
```go
import "github.com/goccy/go-json"
// Drop-in replacement for encoding/json
data, err := json.Marshal(obj)
```
