Gin框架学习|青训营

89 阅读5分钟

安装Gin

go get github.com/gin-gonic/gin

简单搭建Gin框架

你好GIN

可以采用两种方式启动监听

  • 然后通过Http方法绑定路由规则和路由函数。不同于net/http库的路由函数,gin进行了封装,把requestresponse都封装到了gin.Context的上下文环境中。
  • 通过Gin.Run启动
  • 通过http.ListenAndServe
package main
import (
    "net/http""github.com/gin-gonic/gin"
)
func Index(context *gin.Context) {
    context.String(200, "hell Gin")
}
func main() {
    //创建一个路由
    rou := gin.Default()
    // 绑定路由规则和路由函数,访问/index的路由,将由对应的函数去处理
    rou.GET("/index", Index)
    // 启动监听,gin会把web服务器运行在本机的8080端口上
    // 启动方式一 :
    rou.Run(":8080")
    // 启动方式二 : 原生http服务的方式
    http.ListenAndServe(":8888", rou)
}

在浏览器上输入localhost:8080/index则会弹出以下界面

image-20230811164517082

gin.Context

在 Gin 中,Context 是一个非常重要的概念,用于处理 HTTP 请求和响应。在 Gin 的处理流程中,Context 贯穿整个处理过程,用于传递请求和响应的信息。

Context 中封装了原生的 Go HTTP 请求和响应对象,同时还提供了一些方法,用于获取请求和响应的信息、设置响应头、设置响应状态码等操作。

在 Gin 中,Context 是通过中间件来传递的。在处理 HTTP 请求时,Gin 会依次执行注册的中间件,每个中间件可以对 Context 进行一些操作,然后将 Context 传递给下一个中间件。

响应机制

响应字符串

rou.GET("/txt", func(c *gin.Context) {
        c.String(http.StatusOK, "返回txt")
    })

image-20230811165922279

响应JSON

func _json(c *gin.Context) {
    c.JSON(200, 200)
}

image-20230811170250547

响应结构体,map和直接响应json

func _json(c *gin.Context) {
    type User struct {
        Username string
        Age      uint
        Address  string
    }
    user := User{"王涛", 23, "山西省大同市"}
    c.JSON(200, user)
}

image-20230811170607696

响应xml

func _xml(c *gin.Context) {
    c.XML(200, gin.H{"user": "xsq", "message": "happy", "like": "play shopping", "status": http.StatusOK, "data": gin.H{"username": "wangtao", "age": 8}})
}

image-20230811171002011

响应yaml

func _yaml(c *gin.Context) {
    c.YAML(200, gin.H{"user": "ys", "message": "hello", "status": http.StatusOK, "data": gin.H{"username": "大黄", "age": 8}})
}

文件响应

unc main() {
    //创建一个路由
    rou := gin.Default()
    // 在go中,没有相对文件的路径,只有相对于项目的路径
    // 网页请求这个静态目录的前缀,第二个参数是一个目录,注意:前缀不能重复
    rou.StaticFS("/static", http.Dir("static/static"))
    // 配置单个文件   网络请求的路由,文件的路径
    rou.StaticFile("bizhi.png", "static/bizhi.png")
}

image-20230811204828270

重定向

重定向(Redirect)就是通过各种方法将各种网络请求重新定个方向转到其它位置

router.GET("/redirect", func(c *gin.Context) {
    //支持内部和外部的重定向
    c.Redirect(http.StatusMovedPermanently, "http://www.baidu.com/")
})
func _redirect(c *gin.Context) {
    c.Redirect(302, "https://www.baidu.com/")
}

image-20230811172816884

状态码

  • 301 Moved Permanently

被请求的资源已永久移动到新位置,并且将来任何对此资源的引用都应该使用本响应返回的若干个 URI 之一。如果可能,拥有链接编辑功能的客户端应当自动把请求的地址修改为从服务器反馈回来的地址。除非额外指定,否则这个响应也是可缓存的。

  • 302 Found

请求的资源现在临时从不同的 URI 响应请求。由于这样的重定向是临时的,客户端应当继续向原有地址发送以后的请求。只有在Cache-Control或Expires中进行了指定的情况下,这个响应才是可缓存的。

Gin框架设计

路由文件adminRoutes.go

package routing
​
import "github.com/gin-gonic/gin"func AdminRoutesInit(route *gin.Engine) {
    //Engine是gin里面的一个结构体,里面有很多字段,它还嵌套了RouterGroup结构体
    adminTRouter := route.Group("/admin")
    {
        adminTRouter.GET("/user", func(c *gin.Context) {
            c.JSON(200, gin.H{
                "message": "user-ok",
            })
        })
        adminTRouter.GET("/news", func(c *gin.Context) {
            c.JSON(200, gin.H{
                "message": "news-ok",
            })
        })
    }
}

路由文件apiRoutes.go

package routing
​
import "github.com/gin-gonic/gin"func ApiRoutesInit(routes *gin.Engine) {
    apiroute := routes.Group("/api")
    {
        apiroute.GET("/user", func(c *gin.Context) {
            c.JSON(200, gin.H{
                "username": "张三",
            })
        })
        apiroute.GET("/news", func(c *gin.Context) {
            c.JSON(200, gin.H{
                "title": "新闻",
            })
        })
    }
}
​

路由文件default Routes.go

package routing
​
import "github.com/gin-gonic/gin"func DefaultRoutesInit(router *gin.Engine) {
    defaultRoute := router.Group("/")
    {
        defaultRoute.GET("/", func(c *gin.Context) {
            c.String(200, "首先")
        })
    }
}

主文件main.go

package main
​
import (
    "github.com/gin-gonic/gin"
    "main.go/routing"
)
​
// form:"username":这个标签表示在处理HTTP表单数据时,该字段应该对应于表单中的 "username" 参数。这意味着在从HTTP请求中解析表单数据时,将会使用 "username" 参数的值填充到这个字段。
// json:"user":这个标签表示在JSON编码和解码中,该字段应该对应于JSON对象中的 "user" 键。这意味着在将该结构体实例转换为JSON时,字段会以 "user" 键表示,而在从JSON解码时,会使用 "user" 键的值填充到这个字段。
type UserInfo struct {
    Username string `form:"username" json:"user"`
    Password string `form:"password" json:"password"`
}
​
func main() {
    r := gin.Default()
    routing.AdminRoutesInit(r)
    routing.ApiRoutesInit(r)
    routing.DefaultRoutesInit(r)
    r.Run(":8080")
}

Gin中自定义控制器

可以把控制器方法从路由器中单独抽离出来,并与结构体进行绑定,这样就能绑定父类的方法,从而实现,controller-service:

// 控制器方法
type UserController struct{}
​
func (con UserController) Index(c *gin.Context) {
    c.String(200, "用户列表")
}
​
func (con UserController) Add(c *gin.Context) {
    c.String(200, "用户列表-add")
}
​
func AdminRoutesInit(route *gin.Engine) {
    adminRouter := route.Group("/admin")
    {
        adminRouter.GET("/user/index", UserController{}.Index)
        adminRouter.GET("/user/add", UserController{}.Add)
    }
}

Gin中间件

Gin框架允许开发者在处理请求的过程中,加入用户自己的钩子函数。这个钩子函数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证、权限校验、数据分页、记录日志、耗时统计等。通俗的讲:中间件就是匹配路由前和匹配路由完成后执行的一系列操作;

func initMiddleware(c *gin.Context) {
    fmt.Println("我是第一个中间件")
    start := time.Now().UnixNano() //获取此时纳秒的时间戳
    c.Next()                       //作用:先执行后面的程序,最后再执行c.Next()后面的程序
    end := time.Now().UnixNano()
    fmt.Println("2-我是一个中间件")
    fmt.Println(end - start) //求出之间的时间就是程序执行的时间
}