Gin HTTP Web Framework for Go

repository·master·Indexed Apr 14, 2026

https://github.com/gin-gonic/gin

Gin is a high-performance HTTP web framework written in Go, designed for building REST APIs, web applications, and microservices. It features a zero-allocation router based on httprouter, middleware support, automatic JSON binding, and crash-free recovery. The framework supports route grouping, path parameters, file uploads, and custom JSON libraries via build tags like jsoniter, go_json, and sonic. Users can disable MsgPack rendering with the nomsgpack tag to reduce binary size. Version 1.12.0 includes new features and performance improvements.

Tokens
40.1K
Snippets
109
Records
148
Agent score
100%

What's inside gin-gonic/gin

  1. Performance Summary of Gin Web Framework

    master

    Gin is a high-performance HTTP web framework. In real-world routing workloads (modeled after the GitHub API with 203 routes), Gin ranks in the top tier of routers, achieving approximately 9,944 ns/op with zero heap allocations and zero allocations per operation. This makes it highly suitable for latency-sensitive applications.

    /* 
    Benchmark Results (GitHub API - 203 routes):
    | Rank | Router | ns/op | B/op | allocs/op |
    | :--: | :--- | ---: | ---: | ---: |
    | 1 | Gin | 9,944 | 0 | 0 |
    */
  2. Initialize Gin with or without default middleware

    master

    Gin provides two ways to initialize a router:

    1. gin.Default(): Creates a router with Logger and Recovery middleware already attached.
    2. gin.New(): Creates a blank router without any middleware by default. Use this if you want full control over your middleware stack.
    // Default with Logger and Recovery middleware
    r := gin.Default()
    
    // Blank Gin without middleware
    r := gin.New()
  3. Bind custom unmarshaler for types

    master

    If you want to customize how a specific type is parsed from a string (like a date format), you can implement the encoding.TextUnmarshaler interface. To tell Gin to use this interface, add parser=encoding.TextUnmarshaler to the uri or form tag.

    Alternatively, if you want to customize how Gin binds the type specifically (and potentially override error messages), implement the binding.BindUnmarshaler interface. If a type implements both, Gin uses BindUnmarshaler by default.

    // Using encoding.TextUnmarshaler
    type Birthday string
    
    func (b *Birthday) UnmarshalText(text []byte) error {
      *b = Birthday(strings.Replace(string(text), "-", "/", -1))
      return nil
    }
    
    type request struct {
      Birthday Birthday `form:"birthday,parser=encoding.TextUnmarshaler"` 
    }
  4. Explore Gin middleware and ecosystem

    master

    Gin supports an extensible middleware system for tasks like authentication, logging, CORS, and more. You can find official and community middleware in these repositories:

    • gin-contrib: Official collection including JWT, Basic Auth, Sessions, CORS, Rate limiting, Compression, Logging, Metrics, Tracing, Static file serving, and Template engines.
    • gin-gonic/contrib: Additional community-contributed middleware.
  5. Handle Goroutines inside middleware or handlers

    master

    When starting a new Goroutine inside a Gin handler or middleware, do not use the original *gin.Context. The original context is not thread-safe and may be recycled before the Goroutine finishes. Instead, use c.Copy() to create a read-only copy of the context specifically for use within the Goroutine.

    r.GET("/long_async", func(c *gin.Context) {
      // create copy to be used inside the goroutine
      cCp := c.Copy()
      go func() {
        time.Sleep(5 * time.Second)
        // use the copied context "cCp"
        log.Println("Done! in path " + cCp.Request.URL.Path)
      }()
    })
  6. Bind request body multiple times

    master

    Standard binding methods like ShouldBindJSON or ShouldBindXML consume the c.Request.Body stream. Once read, the body is empty (EOF) and cannot be read again by another binding call.

    To bind the same request body into different structs (e.g., to try multiple formats), use ShouldBindBodyWith. This method reads the body and stores it in the Gin context so it can be reused.

    Note: This has a slight performance impact because the body is buffered. Use it only when necessary. It is primarily useful for JSON, XML, MsgPack, and ProtoBuf formats.

    // Use ShouldBindBodyWith to allow multiple bindings
    if err := c.ShouldBindBodyWith(&objA, binding.JSON); err == nil {
      // Success with JSON
    } else if err := c.ShouldBindBodyWith(&objB, binding.XML); err == nil {
      // Success with XML
    }
  7. Model binding and validation in Gin

    master

    Gin allows you to bind request data (JSON, XML, YAML, TOML, or form values) into Go structs. It uses go-playground/validator/v10 for validation. To ensure correct binding, you must decorate your struct fields with the appropriate tags (e.g., json:"fieldname", form:"fieldname", xml:"fieldname").

    There are two main categories of binding methods:

    1. Must Bind (Bind...): These methods (e.g., BindJSON, BindXML) use MustBindWith internally. If binding fails, Gin automatically aborts the request with a 400 Bad Request status and sets the response to text/plain. Use these when you want to enforce binding and don't want to manually handle the error response.
    2. Should Bind (ShouldBind...): These methods (e.g., ShouldBindJSON, ShouldBindQuery) return an error if binding fails, allowing the developer to handle the error (e.g., returning a custom JSON error response). This is generally preferred for greater control.

    You can enforce required fields using the binding:"required" tag.

    type Login struct {
      User     string `form:"user" json:"user" xml:"user" binding:"required"`
      Password string `form:"password" json:"password" xml:"password" binding:"required"`
    }
    
    // Inside a handler:
    var json Login
    if err := c.ShouldBindJSON(&json); err != nil {
      c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
      return
    }
  8. Perform graceful shutdown of a Gin server

    master

    To ensure active requests are completed before the server exits, use the http.Server.Shutdown() method. This is typically implemented by listening for OS interrupt signals (like SIGINT or SIGTERM) in a goroutine and then calling Shutdown with a context timeout.

    // +build go1.8
    
    package main
    
    import (
      "context"
      "errors"
      "log"
      "net/http"
      "os"
      "os/signal"
      "syscall"
      "time"
    
      "github.com/gin-gonic/gin"
    )
    
    func main() {
      router := gin.Default()
      router.GET("/", func(c *gin.Context) {
        time.Sleep(5 * time.Second)
        c.String(http.StatusOK, "Welcome Gin Server")
      })
    
      srv := &http.Server{
        Addr:    ":8080",
        Handler: router,
      }
    
      go func() {
        if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
          log.Printf("listen: %s\n", err)
        }
      }()
    
      quit := make(chan os.Signal, 1)
      signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
      <-quit
      log.Println("Shutting down server...")
    
      ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
      defer cancel()
    
      if err := srv.Shutdown(ctx); err != nil {
        log.Fatal("Server forced to shutdown:", err)
      }
    
      log.Println("Server exiting")
    }
  9. Build Gin without MsgPack rendering feature

    master

    To reduce the binary size of your executable, you can disable the MsgPack rendering feature by specifying the nomsgpack build tag during compilation.

    go build -tags=nomsgpack .
  10. Register custom validators

    master

    You can extend Gin's validation capabilities by registering custom validation functions with the underlying validator engine. This is useful for domain-specific logic, such as checking if a date is in the future.

    To do this, access the validator engine via binding.Validator.Engine() and call RegisterValidation.

    var bookableDate validator.Func = func(fl validator.FieldLevel) bool {
      date, ok := fl.Field().Interface().(time.Time)
      if ok {
        today := time.Now()
        if today.After(date) {
          return false
        }
      }
      return true
    }
    
    // In your setup:
    if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
      v.RegisterValidation("bookabledate", bookableDate)
    }
    
    // Use in struct:
    type Booking struct {
      CheckIn time.Time `form:"check_in" binding:"required,bookabledate"` 
    }
  11. Upload single or multiple files

    master

    To handle file uploads, set router.MaxMultipartMemory to limit memory usage (default is 32 MiB).

    Single file: Use c.FormFile("field") to get the file and c.SaveUploadedFile(file, dst) to save it.

    Multiple files: Use c.MultipartForm() to get the form, then iterate over form.File["field[]"].

    router.MaxMultipartMemory = 8 << 20 // 8 MiB
    router.POST("/upload", func(c *gin.Context) {
      file, _ := c.FormFile("file")
      c.SaveUploadedFile(file, "/path/to/destination")
      c.String(http.StatusOK, "'%s' uploaded!", file.Filename)
    })
    router.MaxMultipartMemory = 8 << 20
    router.POST("/upload", func(c *gin.Context) {
      file, _ := c.FormFile("file")
      c.SaveUploadedFile(file, "/path/to/destination")
    })

    Sources: docs/doc.md

  12. Run a Gin application

    master

    To run the application after saving it as main.go:

    1. Execute go run main.go in your terminal.
    2. The server will start listening on 0.0.0.0:8080 (or localhost:8080 on Windows).
    3. Access the endpoint at http://localhost:8080/ping to see the JSON response.
    go run main.go