Some Go web dev notes

Go’s appeal for web development lies in its stable language, strong standard library, and easy deployment of single static binaries, but many engineers note that getting started can be slow compared to “batteries included” frameworks like Rails or Django. Commenters weigh minimalist, stdlib-first approaches against opinionated stacks that bundle routers, ORMs, templating systems, and auth, debating trade-offs in productivity, lock‑in, and long‑term maintainability. Alongside tooling tips (e.g., for GC tuning, container CPU limits, SQLite concurrency, and embedding static assets), critics highlight Go’s verbose error handling and nil semantics as signs it has not fully embraced newer language design ideas, even as its runtime and ecosystem remain widely respected.

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 embed for 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.