Interview Q&A · 13 questions · 8 answered publicly
Go Web Frameworks Interview Questions
Ordered by how often they're asked. Sign in free to see every answer, rate your confidence and run timed mock interviews.
-
Most asked What is the http.Handler interface, and why is it central to Go web development?
Summary
http.Handler has one method, ServeHTTP(http.ResponseWriter, *http.Request). Routers, middleware, frameworks and servers all speak this interface, so pieces compose freely.
Longer Answer
http.HandlerFuncadapts a plain function to the interface. Middleware are functionsfunc(http.Handler) http.Handler. Because Chi, Gin and Echo engines are themselveshttp.Handlers, they run underhttp.Server, test withhttptest, and can host standard middleware.Code Example
func logging(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { log.Println(r.Method, r.URL.Path) next.ServeHTTP(w, r) }) }Key Points
- One method: ServeHTTP.
- HandlerFunc adapts functions.
- Middleware wrap handlers.
- Frameworks are Handlers too (except Fiber).
Deep dive: Go Web Frameworks: Start with net/http
-
Most asked Compare Gin, Echo, Chi and Fiber.
Summary
Chi is a net/http-compatible router; Gin is the most popular framework with its own Context and tag-based binding; Echo is similar but handlers return errors handled centrally; Fiber is Express-like and built on fasthttp, so it isn't net/http compatible.
Longer Answer
Choose by needs and team: standard-library style and no lock-in (Chi), ecosystem and familiarity (Gin), centralised error handling (Echo), Express ergonomics or extreme throughput with simple handlers (Fiber). Router speed rarely matters compared with database time. Keep business logic framework-free either way.
Key Points
- Chi: router, standard handlers.
- Gin: popular, binding/validation.
- Echo: handlers return errors.
- Fiber: fasthttp, not net/http.
Deep dive: Go Web Frameworks: Choosing a Go Framework
-
Most asked How do you test HTTP handlers in Go?
Summary
Use net/http/httptest: build a request with httptest.NewRequest, a recorder with httptest.NewRecorder, call router.ServeHTTP(rec, req), and assert on status, headers and body, usually in table-driven tests with t.Run.
Longer Answer
Inject dependencies via interfaces so tests use fakes. Run with
go test -race ./.... Keep a few integration tests against a real database (e.g. in a container). Fiber apps useapp.Test(req)instead.Key Points
- httptest recorder, no server needed.
- Table-driven subtests.
- Interfaces + fakes; -race in CI.
Deep dive: Go Web Frameworks: Testing Go APIs
-
Most asked How should a Go service use database/sql correctly?
Summary
Open one *sql.DB (a concurrency-safe pool) at startup and share it, configure pool limits, always use placeholders, pass contexts to every query, close rows, check rows.Err(), and translate sql.ErrNoRows to a domain 'not found' error.
Longer Answer
Use transactions (
BeginTx,defer tx.Rollback(),Commit) for multi-step changes, and conditional updates or row locks to prevent check-then-act races. Libraries such as sqlx, sqlc or GORM sit on top; hide them behind a repository interface.Key Points
- One pool, shared.
- Placeholders and contexts.
- Close rows; handle ErrNoRows.
- Transactions for multi-step changes.
Deep dive: Go Web Frameworks: Database Access
-
Most asked How do you implement graceful shutdown for a Go HTTP server?
Summary
Listen for SIGINT/SIGTERM (signal.NotifyContext), then call server.Shutdown(ctx) with a timeout: it stops accepting new connections and waits for in-flight requests to finish before returning.
Longer Answer
Also close other resources (database pools, message consumers) after the server drains, and fail readiness checks at the start of shutdown so load balancers stop sending traffic.
Code Example
ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM) defer stop() go srv.ListenAndServe() <-ctx.Done() shutdownCtx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() srv.Shutdown(shutdownCtx)Key Points
- signal.NotifyContext for SIGTERM.
- server.Shutdown(ctx) drains requests.
- Close resources after; fail readiness first.
Deep dive: Go Web Frameworks: Production Ready
-
Most asked Do you need a web framework in Go? What does Go 1.22's ServeMux provide?
Summary
Often not. Since Go 1.22, http.ServeMux matches methods and path wildcards ("GET /books/{id}", read with r.PathValue), returns 405 for wrong methods, and prefers more specific patterns.
Longer Answer
Frameworks still add route groups, request binding and validation, centralised error handling and helper APIs. Small services and libraries often stay on the standard library for zero dependencies and long-term stability; larger APIs may prefer Chi, Gin or Echo for ergonomics.
Key Points
- Method + wildcard routing since 1.22.
- 405 handling built in.
- Frameworks add groups, binding, validation, errors.
Deep dive: Go Web Frameworks: Start with net/http
-
Most asked How do you pass request-scoped values (like the current user) through middleware in Go?
Summary
Store them in the request's context with context.WithValue, using an unexported key type to avoid collisions, pass r.WithContext(ctx) to the next handler, and read them with a typed helper.
Longer Answer
Frameworks offer equivalents (
c.Set/c.Getin Gin,c.Setin Echo,c.Localsin Fiber), butcontext.Contextis what you should pass into services and repositories so cancellation and deadlines flow through too. Don't use context values for optional function parameters.Code Example
type ctxKey int const userKey ctxKey = 0 func UserFrom(ctx context.Context) (string, bool) { u, ok := ctx.Value(userKey).(string) return u, ok }Key Points
- context.WithValue + private key type.
- Typed accessor helper.
- Pass ctx into services for cancellation.
Deep dive: Go Web Frameworks: Middleware
-
Most asked How do you design consistent error responses in a Go API?
Summary
Define one API error type (status, machine-readable code, message, optional field errors), one function that writes it, and map domain errors to it in one place; unexpected errors become a generic 500 while the real cause is logged.
Longer Answer
Use errors.Is/As to map sentinel and typed domain errors (ErrNotFound → 404, ErrConflict → 409). Echo's central HTTPErrorHandler is built for this; in other frameworks, write a helper or middleware. RFC 9457 (Problem Details) is a standard format to consider.
Key Points
- One error type and writer.
- Map domain errors centrally.
- Never leak internals.
Deep dive: Go Web Frameworks: Validation and Errors
- How does request validation work in Gin?
- Which http.Server timeouts should you set, and why?
- Why must you copy values from a Fiber context that outlive the request?
- Compare GORM, sqlx and sqlc.
- What is log/slog and why use it?