gin入门

举报
yd_254179665 发表于 2025/07/04 14:41:01 2025/07/04
【摘要】 Gin 是一个用 Go 语言编写的高性能 Web 框架,它提供了丰富的功能和灵活的配置选项,适用于构建高效、可扩展的 Web 应用程序。下载gin可以使用go get -u github.com/gin-gonic/gin在 main.go 文件中编写一个简单的 Gin 应用程序package mainimport ( "net/http" "github.com/gin-gon...

Gin 是一个用 Go 语言编写的高性能 Web 框架,它提供了丰富的功能和灵活的配置选项,适用于构建高效、可扩展的 Web 应用程序。

下载gin可以使用

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

main.go 文件中编写一个简单的 Gin 应用程序

package main

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

func main() {
    // 创建一个默认的路由引擎
    r := gin.Default()

    // 定义一个简单的路由
    r.GET("/", func(c *gin.Context) {
        c.String(http.StatusOK, "Hello, Gin!")
    })

    // 启动 HTTP 服务,默认监听 8080 端口
    r.Run()
}

访问http://localhost:8080 可以看到 Hello,Gin!

可以设置路由组

r := gin.Default()

    // 创建一个用户相关的路由组
    userGroup := r.Group("/user")
    {
        userGroup.GET("/profile", getUserProfile)
        userGroup.POST("/login", userLogin)
        userGroup.POST("/register", userRegister)
    }

中间件是处理请求的函数,可以用于日志记录、认证、错误处理等。Gin 框架提供了丰富的中间件支持。

package main

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

func Logger() gin.HandlerFunc {
    return func(c *gin.Context) {
        // 在请求处理之前记录请求信息
        c.Writer.Header().Set("X-My-Header", "my-value")
        c.Next()
        // 在请求处理之后记录响应信息
        c.Writer.Header().Set("X-My-Response-Header", "my-response-value")
    }
}

func Recovery() gin.HandlerFunc {
    return func(c *gin.Context) {
        defer func() {
            if err := recover(); err != nil {
                c.JSON(http.StatusInternalServerError, gin.H{"error": "Internal server error"})
            }
        }()
        c.Next()
    }
}

func main() {
    r := gin.Default()

    // 使用自定义中间件
    r.Use(Logger(), Recovery())

    r.GET("/", func(c *gin.Context) {
        c.String(http.StatusOK, "Hello, Gin!")
    })

    r.Run()
}

这个其实和nodejs的koa,express的中间件差不多,都是洋葱模型。

当访问不存在的路由时也可以定义返回内容

    r.NoRoute(func(c *gin.Context) {
        c.JSON(http.StatusNotFound, gin.H{"code": "404", "message": "Page not found"})
    })

当需要接收参数时可以使用结构体

type User struct {
	ID       int    `json:"id"`
	Username string `json:"username" binding:"required"`
	Password string `json:"password" binding:"required"`
	Age      int    `json:"age"`
}

// 定义一个处理器函数
func createUser(c *gin.Context) {
	var user User
	if err := c.ShouldBindJSON(&user); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	fmt.Println(user.Username)
	// 模拟用户创建
	user.ID = 1
	c.JSON(http.StatusCreated, user)
}

// 定义一个处理器函数
func getUser(c *gin.Context) {
	id := c.Param("id")
	// 模拟从数据库中获取用户
	fmt.Println(id)
	user := User{ID: 1, Username: "testuser", Password: "testpassword", Age: 25}
	c.JSON(http.StatusOK, user)
}

// 定义一个处理器函数
func updateUser(c *gin.Context) {
	id := c.Param("id")
	var user User
	if err := c.ShouldBindJSON(&user); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}
	// 模拟更新用户
	c.JSON(http.StatusOK, gin.H{"message": "User updated", "id": id, "user": user})
}

// 定义一个处理器函数
func deleteUser(c *gin.Context) {
	id := c.Param("id")
	// 模拟删除用户
	c.JSON(http.StatusOK, gin.H{"message": "User deleted", "id": id})
}

gin的原理是使用了前缀树,通过压缩公共前缀来节省空间,提高查询效率。例如,路径 /ping  /ping/hello 可以共享前缀 /ping,从而减少节点数量。每个路由节点会挂载一个函数链,链的前面部分是中间件函数,后面部分是业务处理函数。gin.Context作为请求/响应信息的统一容器,通过sync.Pool高效复用

package main

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

// Engine 结构体中包含一个 sync.Pool 用于复用 Context 对象
type Engine struct {
    pool sync.Pool
    // 其他字段...
}

// ServeHTTP 实现 http.Handler 接口
func (engine *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    // 从对象池中获取一个 Context 对象
    c := engine.pool.Get().(*gin.Context)
    c.writermem.reset(w)
    c.Request = req

    // 重置 Context 对象的状态
    c.reset()

    // 处理 HTTP 请求
    engine.handleHTTPRequest(c)

    // 将处理过的 Context 对象放回对象池
    engine.pool.Put(c)
}

// handleHTTPRequest 处理 HTTP 请求
func (engine *Engine) handleHTTPRequest(c *gin.Context) {
    // 处理请求的逻辑...
}

// Context 结构体
type Context struct {
    // 其他字段...
}

// reset 重置 Context 对象的状态
func (c *Context) reset() {
    // 重置 Context 对象的状态...
}
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。