Some Go web dev notes
Go’s Stability and Long-Term Maintainability
- Many praise Go’s slow evolution and stable standard library. Code can be abandoned for years and then revived with minimal friction.
- Dependency updates tend to be painless compared to JavaScript/frontend ecosystems, where frequent breakage and complex chains of dependencies are common.
- This “boring but stable” quality is viewed as a major, often underrated advantage, especially for tools and long-lived internal apps.
Frameworks vs. Standard Library
- Strong support for a “library over framework” mindset: net/http, standard testing, and basic logging are seen as sufficient for many services.
- Others find the first days in Go frustrating: choosing routers, logging, DB drivers, migrations, DI patterns, etc., is slower than “batteries-included” frameworks like Rails, Django, or .NET.
- Opinionated stacks (Echo, ent, HTMX, Bulma, beego, pagoda, authboss, etc.) divide opinion: some want them for speed; others distrust “magic” and lock‑in.
Routing, Templates, and Web Stack Choices
- Newer net/http features (path parameters, methods) reduce the need for heavy routers; chi is popular as a thin stdlib wrapper; some are moving away from Gin in favor of Echo or chi.
- html/template is seen as powerful but awkward: idiosyncratic APIs, surprising behaviors (e.g., stripping comments), weak typing, and difficult data/threading across nested templates.
- Templ is frequently recommended as a more ergonomic, type-safe alternative that plays well with HTMX.
Databases, SQL, and Transactions
- Common stack patterns: pgx for Postgres, sqlx or Jet for SQL helpers, goose/pgmigrate for migrations, SQLite for small apps.
- sqlc gets mixed reviews: great for simple queries but limited for dynamic queries, complex relationships, and advanced DB features.
- SQLite concurrency is tricky: SQLITE_BUSY errors, WAL mode, BEGIN CONCURRENT, and single-writer patterns are discussed.
- There’s a debate on transaction retries: some argue all DB work should be wrapped in bounded retry loops; others say blind retries can hide misconfiguration and overload the DB.
Deployment, Performance, and Ops
- Static binaries plus
embedfor static assets make deployment trivial (copy one file, maybe add systemd); widely contrasted with Python/Ruby’s virtualenvs, WSGI, and native deps. - Built-in TLS in net/http is considered production-ready; many still front Go with proxies but it’s not required.
- GOMEMLIMIT and GOMAXPROCS/automaxprocs are recommended for containerized deployments to respect memory/CPU limits.
Language Design, Error Handling, and Ergonomics
- Some developers enjoy Go’s explicit error handling and simplicity (“if err != nil” everywhere) and see it as clarity, not noise.
- Others criticize Go as a “1990s” design: nil handling without option types, verbose checks, weaker type system, lack of modern conveniences, and ergonomics issues like the Header.Get API.
- There’s broad agreement that Go’s runtime, tooling, and governance are excellent even where the language itself feels limited or unexpressive.