Gin Introduction

What Gin adds over plain net/http, installing it, and a minimal hello-world server.

What Gin adds over net/http

Go's standard library (net/http) is genuinely production-capable on its own — see the Go track's REST API with net/http page for a from-scratch example. Gin is a web framework built on top of it that removes the boilerplate that starts to hurt once an API grows past a handful of endpoints:

  • A real router with path parameters and groupingr.GET("/users/:id", ...), plus route groups (r.Group("/api/v1")) for shared prefixes and middleware, instead of hand-parsing paths or juggling multiple ServeMux instances.
  • A built-in middleware chainr.Use(...), with c.Next()/c.Abort() control, and per-route middleware, covered in depth on the next page.
  • JSON binding and validation in one callc.ShouldBindJSON(&input) decodes and validates struct tags (binding:"required") in a single line, instead of a manual json.Decode plus hand-written checks.
  • Performance — Gin's router (a radix-tree implementation) is one of the fastest in the Go ecosystem, adding negligible overhead over raw net/http.

Gin doesn't replace your knowledge of net/http — a gin.Context wraps the same underlying http.Request/http.ResponseWriter you'd use directly, and *gin.Engine itself implements http.Handler, so it plugs into anything expecting the standard interface (including net/http's own http.Server).

Installing Gin

Gin is a regular Go module — no separate installer:

Bash
go mod init example.com/ginapp
go get github.com/gin-gonic/gin

A minimal Gin server

Go
package main

import (
    "net/http"

    "github.com/gin-gonic/gin"
)

func main() {
    r := gin.Default() // includes sane default middleware: logging + panic recovery

    r.GET("/ping", func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{
            "message": "pong",
        })
    })

    r.Run(":8080") // shorthand for http.ListenAndServe(":8080", r)
}
Bash
go run main.go
Bash
curl http://localhost:8080/ping
# {"message":"pong"}

gin.Default() vs gin.New(): Default() pre-attaches Gin's Logger() and Recovery() middleware (so a panicking handler returns a 500 instead of crashing the whole process); New() gives you a completely bare engine to configure from scratch.

Path parameters and gin.H

Go
r.GET("/users/:id", func(c *gin.Context) {
    id := c.Param("id")                         // path parameter
    name := c.DefaultQuery("name", "anonymous")  // query parameter with a fallback

    c.JSON(http.StatusOK, gin.H{
        "id":   id,
        "name": name,
    })
})
Bash
curl "http://localhost:8080/users/42?name=Zara"
# {"id":"42","name":"Zara"}

gin.H is simply a shorthand type alias for map[string]any — used purely for readability when building a JSON response inline.

Common mistakes

  • Using gin.New() in production without adding gin.Recovery() back manually — an unhandled panic in a handler then crashes the entire server instead of returning a 500 to that one caller.
  • Forgetting that c.Param("id") always returns a string — you still need to parse it (strconv.Atoi) and check the error before treating it as a number.
  • Running with Gin's default debug mode in production — set gin.SetMode(gin.ReleaseMode) (or the GIN_MODE=release environment variable) to disable the verbose debug output and warnings.

Interview questions

Q: What does gin.Default() give you that gin.New() doesn't? gin.Default() returns an engine with the Logger() and Recovery() middleware already attached — request logging and automatic panic recovery (turning a panic into a 500 response instead of crashing the process). gin.New() returns a bare engine with neither, for full manual control.

Q: Is a Gin application still compatible with net/http? Yes — *gin.Engine implements the standard http.Handler interface, and gin.Context internally wraps the same *http.Request and http.ResponseWriter you'd use with plain net/http. This means Gin apps can be served by the standard http.Server, and you can reach into c.Request/c.Writer directly whenever you need standard-library-level control.