GoLang Gin框架WEB开发功能整理

文章目录

    • (1)gin框架RESTful API示例
    • (2)JSON序列化
    • (3)获取请求参数
    • (4)获取form参数
    • (5)获取JSON参数
    • (6)获取path参数
    • (7)参数绑定
    • (8)文件上传
    • (9)重定向
    • (10)路由和路由组
    • (11)中间件

Gin 是一个用 Go (Golang) 编写的 Web 框架。它具有类似martini-like的 API,由于 httprouter,性能提高了 40 倍,有良好的性能的生产力。本文整理了十几个WEB开发的常用功能实例。

(1)gin框架RESTful API示例

import (
    "github.com/gin-gonic/gin"
    "net/http"
)
 
/**
  RESTful API开发实例
*/
func main() {
    engine := gin.Default()
    engine.GET("/user", func(context *gin.Context) {
        context.JSON(http.StatusOK, gin.H{
            "message": "GET",
        })
    })
    engine.POST("/user", func(context *gin.Context) {
        context.JSON(http.StatusOK, gin.H{
            "message": "POST",
        })
    })
    engine.PUT("/user", func(context *gin.Context) {
        context.JSON(http.StatusOK, gin.H{
            "message": "PUT",
        })
    })
    engine.DELETE("/user", func(context *gin.Context) {
        context.JSON(http.StatusOK, gin.H{
            "message": "DELETE",
        })
    })
    engine.Run(":8088")
}

在这里插入图片描述

(2)JSON序列化

【1】gin.H 是map[string]interface{}的缩写
【2】使用结构体时注意只序列化首字母大写的字段
【3】使用结构体可以通过tag的方式自定义返回的数据名称和形式

func main() {
    engine := gin.Default()
    engine.GET("/json1", func(context *gin.Context) {
        //手动拼接JSON串
        context.JSON(http.StatusOK, gin.H{"name": "张三", "age": 24})
    })
 
    engine.GET("/json2", func(context *gin.Context) {
        //使用结构体方式
        context.JSON(http.StatusOK, Student{"Pete", 12})
    })
 
    engine.Run("127.0.0.1:8088")
}
 
type Student struct {
    Name string `json:"name"`
    Age  int `json:"age"`
}

(3)获取请求参数

【1】context.DefaultQuery(“name”, “默认值”) 当未获取到对应的参数时设置默认值
【2】context.Query(“age”)获取请求参数,如果没有则空

func main() {
    engine := gin.Default()
    engine.GET("/search", func(context *gin.Context) {
        query := context.DefaultQuery("name", "默认值")
        age := context.Query("age")
        fmt.Printf("参数name:  %v  参数age: %v ", query, age)
        //接收到请求后再响应结果
        context.JSON(http.StatusOK, gin.H{"status": "OK", "msg": "message..."})
    })
    engine.Run(":8088")
}

GoLang Gin框架WEB开发功能整理_第1张图片

(4)获取form参数

【1】 context.DefaultPostForm(“name”, “默认值”) 如果未获取到表单参数数据则取默认值
【2】context.PostForm(“age”)如果未获取到表单参数数据则为空
当前端请求的数据通过form表单提交时,例如向/search发送一个POST请求,获取请求数据的方式如下:

engine.POST("/search", func(context *gin.Context) {
    name := context.DefaultPostForm("name", "默认值")
    age := context.PostForm("age")
    fmt.Printf("参数name:  %v  参数age: %v ", name, age)
    //接收到请求后再响应结果
    context.JSON(http.StatusOK, gin.H{"status": "OK", "msg": "message..."})
})

(5)获取JSON参数

【1】使用GetRawData来获取JSON格式的请求参数数据
【2】后台接收到之后可以通过map或者结构体来进行反序列化接收参数

engine.POST("/formJson", func(c *gin.Context) {
    //读取row格式请求体数据
    b, _ := c.GetRawData()
    // 定义map或结构体
    var m map[string]interface{}
    // 反序列化
    _ = json.Unmarshal(b, &m)
    fmt.Println("JSON请求参数", m)
    c.JSON(http.StatusOK, m)
})

(6)获取path参数

【1】通过:参数名称匹配路径参数
【2】使用context.Param(“name”)方式获取路径参数值

//获取路径参数
engine.GET("/search/:name/:age", func(context *gin.Context) {
    name := context.Param("name")
    age:=context.Param("age")
    context.JSON(http.StatusOK, gin.H{"name": name, "age": age,"msg":"路径参数测试"})
})

(7)参数绑定

【1】为了能够更方便的获取请求相关参数,提高开发效率,我们可以基于请求的Content-Type识别请求数据类型并利用反射机制自动提取请求中QueryString、form表单、JSON、XML等参数到结构体中。Gin中所提供的ShouldBind()能够基于请求自动提取JSON、form表单和QueryString类型的数据,并把值绑定到指定的结构体对象。

【2】对于需要绑定的字段值,其字段名称需要首字母大写

【3】对于名称不一致的可以通过tag的方式映射

【4】由于结构体类型是值拷贝,所以在作为参数传递并想要拿到结果则需要传递结构体地址

【5】ShouldBind会按照下面的顺序解析请求中的数据完成绑定:

如果是 GET 请求,只使用 Form 绑定引擎(query)。如果是 POST 请求,首先检查 content-type 是否为 JSON 或 XML,然后再使用 Form(form-data)。

type UserInfo struct {
    UserName string `form:"userName" json:"userName" binding:"required"`
    Password string `form:"password" json:"password" binding:"required"`
}
 
func main() {
    engine := gin.Default()
    engine.GET("/login", func(context *gin.Context) {
        var userInfo UserInfo
        err := context.ShouldBind(&userInfo)
        if err == nil {
            fmt.Printf("login info:%#v\n", userInfo)
            context.JSON(http.StatusOK, gin.H{
                "userName": userInfo.UserName,
                "password": userInfo.Password,
            })
        } else {
            context.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        }
    })
 
 
    engine.POST("/login", func(context *gin.Context) {
        var userInfo UserInfo
        err := context.ShouldBind(&userInfo)
        if err == nil {
            fmt.Printf("login info:%#v\n", userInfo)
            context.JSON(http.StatusOK, gin.H{
                "userName": userInfo.UserName,
                "password": userInfo.Password,
            })
        } else {
            context.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        }
    })
     
    engine.Run(":8088")
}

(8)文件上传

【1】使用context.FormFile(“file”)获取单个文件,使用context.MultipartForm()…File[“file”]获取上传的多个文件

【2】处理multipart forms提交文件时默认的内存限制是32 MiB,可以通过engine .MaxMultipartMemory = 8 << 20 // 8 MiB 修改

【3】文件的获取在开发过程中注意处理异常

【4】通过Context.SaveUploadedFile(file, dst) 简单方便的保存文件到服务器

import (
    "fmt"
    "github.com/gin-gonic/gin"
    "net/http"
)
 
func main() {
    engine := gin.Default()
    //单个文件上传
    engine.POST("/upload", func(context *gin.Context) {
 
        file, err := context.FormFile("file")
        if err != nil {
            context.JSON(http.StatusInternalServerError, gin.H{
                "message": err.Error(),
            })
            return
        }
        dst := fmt.Sprintf("./src/file/%s", file.Filename)
        // 上传文件到指定的目录
        _ = context.SaveUploadedFile(file, dst)
        context.JSON(http.StatusOK, gin.H{
            "message": fmt.Sprintf("'%s' 文件已上传", file.Filename),
        })
    })
 
    //多文件上传
    engine.POST("/mulUpload", func(context *gin.Context) {
        // Multipart form
        form, _ := context.MultipartForm()
        files := form.File["file"]
        for _, file := range files {
            dst := fmt.Sprintf("./src/file/%s", file.Filename)
            // 上传文件到指定的目录
            _ = context.SaveUploadedFile(file, dst)
        }
        context.JSON(http.StatusOK, gin.H{
            "message": fmt.Sprintf("%d 多文件已上传", len(files)),
        })
    })
    engine.Run(":8088")
}

GoLang Gin框架WEB开发功能整理_第2张图片
在这里插入图片描述

(9)重定向

【1】使用context.Redirect可以实现内部和外部的重定向

【2】使用gin.Default().HandleContext可以实现路由重定向

// HTTP重定向
engine.GET("/test", func(context *gin.Context) {
    context.Redirect(http.StatusMovedPermanently, "http://www.baidu.com/")
})
 
 
// 路由重定向
engine.GET("/test", func(context *gin.Context) {
    // 指定重定向的URL
    context.Request.URL.Path = "/hello"
    engine.HandleContext(context)
})
engine.GET("/hello", func(context *gin.Context) {
    context.JSON(http.StatusOK, gin.H{"message": "hello"})
})

(10)路由和路由组

【1】普通的路由可以使用engine.GET、engine.POST、engine.PUT、engine.DELETE等方式处理

【2】engine.Any匹配任意请求Method的路由
GoLang Gin框架WEB开发功能整理_第3张图片
【3】为没有配置处理函数的路由添加处理程序,默认情况下它返回404代码,我们也可以通过engine.NoRoute自定义内容处理

【4】对于拥有公共前缀的路由,为了书写方便看着清晰,我们可以通过路由组的方式来管理,engine.Group(“/student”)就是定义了一个/student前缀的路由组,下面实例中路由组{}是可选的,可以保留也可以去掉

【5】注意,路由组内是可以继续嵌套路由组的

import (
    "github.com/gin-gonic/gin"
    "net/http"
)
 
/**
  路由和路由组
*/
func main() {
    engine := gin.Default()
    //普通路由
    engine.GET("/demo", func(context *gin.Context) {
        context.JSON(http.StatusOK, gin.H{"msg": "demo"})
    })
    //匹配任意请求Method的路由
    engine.Any("/any", func(context *gin.Context) {
        context.JSON(http.StatusOK, gin.H{"msg": "any"})
    })
    //处理未匹配的路由
    engine.NoRoute(func(context *gin.Context) {
        context.JSON(http.StatusNotFound, gin.H{"msg": "NoRoute"})
    })
    //路由组
    userGroup:=engine.Group("/user")
    {
        userGroup.GET("/list", func(context *gin.Context) {
            context.JSON(http.StatusNotFound, gin.H{"msg": "user.list"})
        })
        userGroup.POST("/add", func(context *gin.Context) {
            context.JSON(http.StatusNotFound, gin.H{"msg": "user.add"})
        })
    }
    stuGroup:=engine.Group("/student")
    {
        stuGroup.GET("/list", func(context *gin.Context) {
            context.JSON(http.StatusNotFound, gin.H{"msg": "student.list"})
        })
        stuGroup.POST("/add", func(context *gin.Context) {
            context.JSON(http.StatusNotFound, gin.H{"msg": "student.add"})
        })
    }
    engine.Run(":8088")
}

(11)中间件

【1】Gin框架允许开发者在处理请求的过程中,加入用户自己的钩子(Hook)函数。这个钩子函数就叫中间件,中间件适合处理一些公共的业务逻辑,比如登录认证、权限校验、数据分页、记录日志、耗时统计等。

【2】Gin中间件需要是gin.HandlerFunc类型,如下图所示负责处理路由的就是这些HandlerFunc,可以看到如下是支持可变参数的,在执行的过程中是依次
在这里插入图片描述
【3】在中间件执行的过程中,可以使用Gin框架提供的程序链相关的API完成特定的需求功能;

func (c *Context) Next() : 执行程序链后面的中间件,暂时挂起当前程序

func (c *Context) Abort() : 阻止调用后续的程序链中间件,但不会停止当前处理程序。比如在进行授权认证时,如果认证失败则不进行后续执行。

【4】针对全部的处理,比如日志、安全、权限等等可以使用全局注册的方式,对于特定组或者特定路由的处理可以使用单个配置

【5】当全局注册多个中间件,其执行顺序如下图所示,和Java程序员所熟知的过滤器拦截器都是类似的

【6】对于程序链中在上下文设值和取值可以通过context.Set()和context.get()处理,键一个字符串类型,值是空接口类型
GoLang Gin框架WEB开发功能整理_第4张图片

//统计请求耗时
func computeCost() gin.HandlerFunc {
    return func(context *gin.Context) {
        start := time.Now()
        context.Set("message", "Hello")
        context.Next()
        cost := time.Since(start)
        fmt.Printf("处理耗时%d:", cost)
    }
}
 
func main() {
    engine := gin.Default()
    //全局注册中间件
    engine.Use(computeCost())
    //下面的第二个参数就是一个中间件,可以传入多个
    engine.GET("/demo", func(context *gin.Context) {
        value, exists := context.Get("message")
        if exists {
            context.JSON(http.StatusOK, gin.H{"msg": value})
        }
    })
    engine.Run(":8088")
}

在这里插入图片描述

你可能感兴趣的:(Go语言,Go,golang,gin)