Announcement

👇Official Account👇

图片

Welcome to join the group & private message

Article first/tail QR code

Skip to content

Gin 框架实战指南

掌握 Go 语言最流行的 Web 框架,构建高性能 Web 应用

什么是 Gin

Gin 是 Go 语言中一个高性能的 HTTP Web 框架,具有以下特点:

  • 高性能:基于 httprouter,路由性能极快
  • 中间件支持:易于扩展的中间件机制
  • 参数绑定:支持 JSON、XML、表单等多种格式
  • 验证:内置请求验证功能
  • 错误管理:方便的错误处理机制

快速开始

安装

bash
go get -u github.com/gin-gonic/gin

Hello World

go
package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	// 创建默认路由引擎
	r := gin.Default()
	
	// 定义路由
	r.GET("/", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{
			"message": "Hello World!",
		})
	})
	
	// 启动服务
	r.Run(":8080")
}

路由系统

基本路由

go
package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	r := gin.Default()
	
	// GET 请求
	r.GET("/users", getUsers)
	
	// POST 请求
	r.POST("/users", createUser)
	
	// PUT 请求
	r.PUT("/users/:id", updateUser)
	
	// DELETE 请求
	r.DELETE("/users/:id", deleteUser)
	
	// 支持所有方法
	r.Any("/any", handleAny)
	
	r.Run(":8080")
}

func getUsers(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"message": "Get users"})
}

func createUser(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"message": "Create user"})
}

func updateUser(c *gin.Context) {
	id := c.Param("id")
	c.JSON(http.StatusOK, gin.H{"message": "Update user " + id})
}

func deleteUser(c *gin.Context) {
	id := c.Param("id")
	c.JSON(http.StatusOK, gin.H{"message": "Delete user " + id})
}

func handleAny(c *gin.Context) {
	c.JSON(http.StatusOK, gin.H{"method": c.Request.Method})
}

路由参数

go
package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	r := gin.Default()
	
	// 路径参数
	r.GET("/users/:id", func(c *gin.Context) {
		id := c.Param("id")
		c.JSON(http.StatusOK, gin.H{"id": id})
	})
	
	// 多个路径参数
	r.GET("/users/:id/posts/:postId", func(c *gin.Context) {
		userId := c.Param("id")
		postId := c.Param("postId")
		c.JSON(http.StatusOK, gin.H{
			"userId": userId,
			"postId": postId,
		})
	})
	
	// 查询参数
	r.GET("/search", func(c *gin.Context) {
		keyword := c.Query("keyword")
		page := c.DefaultQuery("page", "1")
		
		c.JSON(http.StatusOK, gin.H{
			"keyword": keyword,
			"page":    page,
		})
	})
	
	// 数组查询参数
	r.GET("/filter", func(c *gin.Context) {
		tags := c.QueryArray("tag")
		c.JSON(http.StatusOK, gin.H{"tags": tags})
	})
	
	r.Run(":8080")
}

路由组

go
package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	r := gin.Default()
	
	// 公开路由
	r.GET("/", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{"message": "Welcome"})
	})
	
	// API 路由组
	api := r.Group("/api")
	{
		api.GET("/status", func(c *gin.Context) {
			c.JSON(http.StatusOK, gin.H{"status": "ok"})
		})
		
		// v1 版本
		v1 := api.Group("/v1")
		{
			v1.GET("/users", getUsersV1)
			v1.GET("/users/:id", getUserV1)
		}
		
		// v2 版本
		v2 := api.Group("/v2")
		{
			v2.GET("/users", getUsersV2)
			v2.GET("/users/:id", getUserV2)
		}
	}
	
	// 需要认证的路由组
	authorized := r.Group("/admin")
	authorized.Use(AuthMiddleware())
	{
		authorized.GET("/dashboard", dashboard)
		authorized.GET("/settings", settings)
	}
	
	r.Run(":8080")
}

func AuthMiddleware() gin.HandlerFunc {
	return func(c *gin.Context) {
		token := c.GetHeader("Authorization")
		if token == "" {
			c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
				"error": "Unauthorized",
			})
			return
		}
		c.Next()
	}
}

参数绑定与验证

表单绑定

go
package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

type LoginForm struct {
	Username string `form:"username" binding:"required"`
	Password string `form:"password" binding:"required,min=6"`
}

func main() {
	r := gin.Default()
	
	r.POST("/login", func(c *gin.Context) {
		var form LoginForm
		
		if err := c.ShouldBind(&form); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"error": err.Error(),
			})
			return
		}
		
		c.JSON(http.StatusOK, gin.H{
			"message": "Login successful",
			"user":    form.Username,
		})
	})
	
	r.Run(":8080")
}

JSON 绑定

go
package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

type CreateUserRequest struct {
	Name     string `json:"name" binding:"required,min=2,max=50"`
	Email    string `json:"email" binding:"required,email"`
	Age      int    `json:"age" binding:"gte=0,lte=150"`
	Password string `json:"password" binding:"required,min=8"`
}

func main() {
	r := gin.Default()
	
	r.POST("/users", func(c *gin.Context) {
		var req CreateUserRequest
		
		if err := c.ShouldBindJSON(&req); err != nil {
			c.JSON(http.StatusBadRequest, gin.H{
				"error": err.Error(),
			})
			return
		}
		
		// 创建用户逻辑
		user := gin.H{
			"id":    1,
			"name":  req.Name,
			"email": req.Email,
			"age":   req.Age,
		}
		
		c.JSON(http.StatusCreated, user)
	})
	
	r.Run(":8080")
}

中间件

自定义中间件

go
package main

import (
	"fmt"
	"github.com/gin-gonic/gin"
	"net/http"
	"time"
)

// Logger 中间件
func Logger() gin.HandlerFunc {
	return func(c *gin.Context) {
		start := time.Now()
		path := c.Request.URL.Path
		raw := c.Request.URL.RawQuery
		
		// 处理请求
		c.Next()
		
		// 记录日志
		latency := time.Since(start)
		clientIP := c.ClientIP()
		method := c.Request.Method
		statusCode := c.Writer.Status()
		
		if raw != "" {
			path = path + "?" + raw
		}
		
		fmt.Printf("[GIN] %v | %3d | %13v | %15s | %-7s %s\n",
			start.Format("2006/01/02 - 15:04:05"),
			statusCode,
			latency,
			clientIP,
			method,
			path,
		)
	}
}

// Recovery 中间件
func Recovery() gin.HandlerFunc {
	return func(c *gin.Context) {
		defer func() {
			if err := recover(); err != nil {
				c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{
					"error": "Internal Server Error",
				})
			}
		}()
		c.Next()
	}
}

// CORS 中间件
func CORS() gin.HandlerFunc {
	return func(c *gin.Context) {
		c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
		c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
		c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
		
		if c.Request.Method == "OPTIONS" {
			c.AbortWithStatus(http.StatusNoContent)
			return
		}
		
		c.Next()
	}
}

func main() {
	r := gin.New()
	
	// 使用自定义中间件
	r.Use(Logger())
	r.Use(Recovery())
	r.Use(CORS())
	
	r.GET("/", func(c *gin.Context) {
		c.JSON(http.StatusOK, gin.H{"message": "Hello"})
	})
	
	r.Run(":8080")
}

实战项目结构

project/
├── main.go
├── config/
│   └── config.go
├── controllers/
│   └── user_controller.go
├── models/
│   └── user.go
├── services/
│   └── user_service.go
├── middlewares/
│   └── auth.go
├── routes/
│   └── routes.go
└── utils/
    └── response.go
go
// main.go
package main

import (
	"github.com/gin-gonic/gin"
	"project/routes"
)

func main() {
	r := gin.Default()
	
	// 注册路由
	routes.RegisterRoutes(r)
	
	r.Run(":8080")
}

总结

Gin 框架提供了:

  1. 高性能路由:基于 httprouter 的快速路由匹配
  2. 灵活中间件:易于扩展的中间件机制
  3. 参数绑定:支持多种数据格式和验证
  4. 丰富功能:错误处理、模板渲染、静态文件等

掌握 Gin,你就能快速构建生产级的 Go Web 应用!

上次更新于: