Go 语言 Gin 框架 封装输出 JSON 数据

4,609 阅读2分钟

什么意思?

  • 在开发时,我们需要统一对外输出 json 信息,场景信息如下:
{
   "code": 0,
   "message": "message",
}

普通操作

  • 在 gin 中,我们需要使用 c.JSONc.AsciiJSON 函数进行 JSON 输出,如下
package main

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

func main() {
    r := gin.Default()
    r.GET("/test", func(c *gin.Context) {
        c.JSON(http.StatusOK, gin.H{
            "code": 0,
            "message": "正常",
            "dataset": gin.H{
                "name": "测试接口"
            },
        })
    })
}

要解决的问题

  • 在上面代码例子中,我们可以看到,如果这样写,那么每次都需要写 balabala 这么多代码
  • 所以就得简化代码,我们可以怎么样简化呢?
    • codemessage 这是最基本字段,无论接口是错误还是正确,这两个字段都必须要输出
    • 其他字段,按需返回,毕竟真实开发过程中,不止有一个 dataset 自定义字段放在第一层

解决问题

  • 既然我们要简化,那就得封装
  • 首先我们需要区分接口错误输出、正确输出,得封装成2个方法
    • SuccessResponse
    • ErrorResponse

为什么需要区分呢?

  • 首先,正常开发需求中,codemessage 大多数时候是默认值,只有在特定接口返回特定信息
  • 但是,Go 不支持默认值写法,所以经过我的一顿操作,代码如下:
package main

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

func SuccessResponse(data ...interface{}) gin.H {
	code := 0
	message := "成功"
	params := gin.H{}

	for _, value := range data {
		switch value.(type) {
		case int:
			code = value.(int)
		case string:
			message = value.(string)
		case gin.H:
			params = value.(gin.H)
		}
	}

	return Response(code, message, params)
}

func ErrorResponse(data ...interface{}) gin.H {
	code := -1
	message := "错误"
	params := gin.H{}

	for _, value := range data {
		switch value.(type) {
		case int:
			code = value.(int)
		case string:
			message = value.(string)
		case gin.H:
			params = value.(gin.H)
		}
	}

	return Response(code, message, params)
}

func Response(code int, message string, params gin.H) gin.H {
	response := gin.H{
		"code":    code,
		"message": message,
	}

	for index, value := range params {
		response[index] = value
	}

	return response
}

func main() {
	r := gin.Default()
	
	r.GET("/1", func(c *gin.Context) {
		c.JSON(http.StatusOK, SuccessResponse(0))
	})
	r.GET("/2", func(c *gin.Context) {
		c.JSON(http.StatusOK, SuccessResponse("这是2接口"))
	})
	r.GET("/3", func(c *gin.Context) {
		c.JSON(http.StatusOK, SuccessResponse(gin.H{
			"dataset": gin.H{
				"goods": []int{123,456},
			},
		}))
	})
	r.GET("/4", func(c *gin.Context) {
		c.JSON(http.StatusOK, SuccessResponse(0, gin.H{
			"dataset": gin.H{
				"goods": []int{123,456},
			},
		}))
	})
	r.GET("/5", func(c *gin.Context) {
		c.JSON(http.StatusOK, SuccessResponse("这是5接口", gin.H{
			"dataset": gin.H{
				"goods": []int{123,456},
			},
		}))
	})
	r.GET("/6", func(c *gin.Context) {
		c.JSON(http.StatusOK, SuccessResponse(2, "这是6接口", gin.H{
			"dataset": gin.H{
				"goods": []int{123,456},
			},
		}))
	})

	_ = r.Run()
}

代码分析

  • 通过上面代码,可以看到,通过声明参数为 interface{} 类型,实现了对参数的动态变化,通过封装方法,内置了默认返回值
  • 可以自由灵活的进行传参,简化代码输出自己想要的数据(想要凑代码行数的请忽略此文章)