* Move Go plugin overlay from languages/go/ to plugin/languages/go/ Aligns Go with the Java/Python/JavaScript convention where all language overlays live under plugin/languages/<lang>/. The Makefile already discovers from plugin/languages/* so Go is now included in builds. * Remove accidental read-tracker changes * Ignore .codeflash/observability/ in gitignore
2.9 KiB
2.9 KiB
Library Replacement Guide — Go
When to Consider
All three conditions must hold:
- Profiling evidence: Library accounts for >15% of cumtime
- Plateau evidence: Domain agent tried to reduce calls, cache results — still plateaued
- 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
# 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
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
# Install easyjson
go install github.com/mailru/easyjson/...@latest
# Generate marshalers
easyjson -all pkg/model/types.go
Option B: Manual marshaling for critical paths
// 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
import "github.com/goccy/go-json"
// Drop-in replacement for encoding/json
data, err := json.Marshal(obj)