gin-gonic / gin

Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.
https://gin-gonic.com/
MIT License
77.95k stars 7.97k forks source link

how to wrap function to gin(c *gin.Context) #1873

Open awkj opened 5 years ago

awkj commented 5 years ago

Description

My work function alway is signature

function(ctx context.Contex, req SomeStrcut) ( ret OtherStrcut,err error)

I wish to add a wrap function to wrap it, when err is nil I return

c.JSON(200, 
    gin.H{
      "code":err.Code,
      "msg":err.Error(),
      "data":nil,
     }

other return

c.JSON(200, 
    gin.H{
      "code":0,
      "msg":"",
      "data":ret,
     }

and , if gin must implement `func (c *gin.Context) to add router I try to write as

func Sum(ctx context.Context, req Req) (ret Resp, err error) {
    return
}
func Router() *gin.Engine {
    r := gin.Default()

    r.POST("/sum", func(c *gin.Context) {
        var req controller.Req
        err := c.ShouldBindJSON(&req)
        if err != nil && err != io.EOF {
            WriteJSON(c, nil, err)
            return
        }

        resp, err := controller.Sum(c.Request.Context(), req)
        WriteJSON(c, resp, err)
    })

    return r
}

func WriteJSON(c *gin.Context, resp interface{}, err error) {
    if err != nil {
        c.JSON(200, gin.H{
            "code":    400,
            "message": err.Error(),
            "data":    nil,
        })
    } else {
        c.JSON(200, gin.H{
            "code":    0,
            "message": "",
            "data":    resp,
        })
    }
}

but I must add this repeat code when I add a function, have better solution to write it ?

Screenshots

erikbos commented 3 years ago

Try

package main

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

func main() {
    r := gin.Default()
    r.POST("/status", wrapper(handler))
    r.Run(":8080")
}

func wrapper(f func(c *gin.Context) (string, error)) gin.HandlerFunc {

    return func(c *gin.Context) {
        _, err := f(c)
        if err != nil {
            c.JSON(503, gin.H{"status": err})
            return
        }
        c.JSON(200, gin.H{"status": "OK"})
    }
}

func handler(c *gin.Context) (string, error) {

    var status string
    if err := c.ShouldBindJSON(&status); err != nil {
        return "failed", err
    }
    return status, nil
}