[Series] go-gin-api planning directory and parameter validation (two)

Outline

First synchronization under the project:

Share articles on the use of go modules initialize the project, we share this article:

  • Planning Your Directory Structure
  • Model binding and validation
  • Custom validator
  • Develop API returns structure

Ado, let's get started.

Planning Your Directory Structure

├─ go-gin-api
│  ├─ app
│     ├─ config           //配置文件
│        ├─ config.go
│     ├─ controller       //控制器层
│        ├─ param_bind
│        ├─ param_verify
│        ├─ ...
│     ├─ model            //数据库ORM
│        ├─ proto
│        ├─ ...
│     ├─ repository       //数据库操作层
│        ├─ ...
│     ├─ route            //路由
│        ├─ middleware
│        ├─ route.go
│     ├─ service          //业务层
│        ├─ ...
│     ├─ util             //工具包
│        ├─ ...
│  ├─ vendor  //依赖包
│     ├─ ...
│  ├─ go.mod
│  ├─ go.sum
│  ├─ main.go //入口文件

The above is my custom directory structure, you can also go to define according to their own habits.

The main controller layer controller over the data submitted to verify and validate the completed data transmission to a service processing.

In gin framework, there are two authentication parameters:

1, model binding and validation.

2, custom validator.

Wherein the directory param_bind, the stored data binding parameters, the directory param_verifystorage is the custom validator.

Next, let us be simple to achieve.

Model binding and validation

For example, there is a product created interface, the trade name can not be empty.

Configuring Routing (route.go):

ProductRouter := engine.Group("")
{
    // 新增产品
    ProductRouter.POST("/product", product.Add)

    // 更新产品
    ProductRouter.PUT("/product/:id", product.Edit)

    // 删除产品
    ProductRouter.DELETE("/product/:id", product.Delete)

    // 获取产品详情
    ProductRouter.GET("/product/:id", product.Detail)
}

Parameter binding (param_bind / product.go):

type ProductAdd struct {
    Name string `form:"name" json:"name" binding:"required"`
}

Call controller (controller / product.go):

if err := c.ShouldBind(&param_bind.ProductAdd{}); err != nil {
    utilGin.Response(-1, err.Error(), nil)
    return
}

When we use request Postman analog post, name does not pass or pass parameters is empty, there will be:

Key: 'ProductAdd.Name' Error:Field validation for 'Name' failed on the 'required' tag

This is to use the parameter settings binding:"required".

So what can the use of binding parameters, documentation is it?

Have. Gin using go-playground / validator.v8 be verified, related documentation:

https://godoc.org/gopkg.in/go-playground/validator.v8

Next, we realize what a custom validator.

Custom validator

For example, there is a product created interface, the trade name can not be empty and the parameter name can not equal to admin.

This is similar to business needs, not binding methods exist, we need to write your own authentication methods can be achieved.

Custom authentication methods (param_verify / product.go)

func NameValid (
    v *validator.Validate, topStruct reflect.Value, currentStructOrField reflect.Value,
    field reflect.Value, fieldType reflect.Type, fieldKind reflect.Kind, param string,
) bool {
    if s, ok := field.Interface().(string); ok {
        if s == "admin" {
            return false
        }
    }
    return true
}

Parameter binding (param_bind / product.go):

type ProductAdd struct {
    Name string `form:"name" json:"name" binding:"required,NameValid"`
}

But also bind validator:

// 绑定验证器
if v, ok := binding.Validator.Engine().(*validator.Validate); ok {
    v.RegisterValidation("NameValid", param_verify.NameValid)
}

When we use request Postman analog post, name does not pass or pass parameters is empty, there will be:

Key: 'ProductAdd.Name' Error:Field validation for 'Name' failed on the 'required' tag

When the name = admin:

Key: 'ProductAdd.Name' Error:Field validation for 'Name' failed on the 'NameValid' tag

OK, verify the above two are in force!

The above are output in the console, you can not return a Json data structure it?

can. Then we develop the API returns structure.

Develop API returns structure

{
    "code": 1,
    "msg": "",
    "data": null
}

API returns a configuration interface basically three fields.

Code = 1 indicates a successful example, code = -1 indicates failure.

msg represents message.

data indicates that the data to return.

So, how do we achieve it in gin framework, based on the very simple c.JSON()method of encapsulation can directly look at the code.

package util

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

type Gin struct {
    Ctx *gin.Context
}

type response struct {
    Code     int         `json:"code"`
    Message  string      `json:"msg"`
    Data     interface{} `json:"data"`
}

func (g *Gin)Response(code int, msg string, data interface{}) {
    g.Ctx.JSON(200, response{
        Code    : code,
        Message : msg,
        Data    : data,
    })
    return
}

Call controller (controller / product.go):

utilGin := util.Gin{Ctx:c}
if err := c.ShouldBind(&param_bind.ProductAdd{}); err != nil {
    utilGin.Response(-1, err.Error(), nil)
    return
}

When we use request Postman analog post, name does not pass or pass parameters is empty, there will be:

{
    "code": -1,
    "msg": "Key: 'ProductAdd.Name' Error:Field validation for 'Name' failed on the 'required' tag",
    "data": null
}

When the name = admin:

{
    "code": -1,
    "msg": "Key: 'ProductAdd.Name' Error:Field validation for 'Name' failed on the 'NameValid' tag",
    "data": null
}

OK, verify the above two are in force!

Source Address

https://github.com/xinliangnote/go-gin-api

go-gin-api series

Guess you like

Origin www.cnblogs.com/xinliangcoder/p/11423406.html