An overview of the

First of all, synchronize the project overview:

Initializing a project using Go Modules was shared in the previous article. In this article we share:

  • Planning a Directory Structure
  • Model binding and validation
  • Custom validators
  • Specify the API return structure

Without further ado, let’s get started.

Planning a Directory Structure

├─ Go-gin - API │ ├─ app │ ├─ config // Config files │ ├─ Config. Go │ ├─ Param_bind │ ├─ Param_Verify │ ├─ . │ ├─ Heavy Metal Exercises // ├─ Heavy metal Exercises... │ ├─ ├─ Repository // ├─... Routing │ │ ├ ─ the route / / ├ ─ middleware │ ├ ─ route. Go │ ├ ─ service / / business layer │ ├ ─... │ ├─ Heavy Exercises // │ ├─ Heavy Exercises... │ ├─ Bass Exercises // │ ├─... │ ├─ Go. Mod │ ├─ Go. Sum │ ├─ mainCopy the code

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

Controller The controller layer validates the submitted data and passes the validated data to the Service.

In the GIN framework, there are two types of parameter validation:

1. Model binding and validation.

2. Custom validators.

The param_bind directory stores the data bound to the parameter, and the param_verify directory stores the custom validator.

Next, let’s do a simple implementation.

Model binding and validation

For example, there is an interface to create a commodity whose name cannot be empty.

Configuring a route (route.go) :

ProductRouter := engine.Group(""{// add product productrouter.post ("/product", product.add) // Update product productrouter.put ("/product/:id", product.edit) // DELETE product productrouter.delete ("/product/:id", product.delete) // GET product details productrouter.get ("/product/:id", product.Detail)
}
Copy the code

Parameter binding (param_bind/product.go) :

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

Controller call (controller/product.go) :

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

Postman = Postman; Postman = Postman; Postman = Postman; Postman = Postman; Postman = Postman

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

This uses the binding:”required” parameter setting.

What other parameters can binding be used? Is there documentation?

There is. Gin used Go-playground/Validator.v8 for verification.

Godoc.org/gopkg.in/go…

Next, let’s implement a custom validator.

Custom validators

For example, there is an interface to create a commodity whose name cannot be empty and whose parameter name cannot be equal to admin.

Similar to this business requirement, existing methods cannot be binding, so we need to write our own verification methods to achieve it.

Custom verification 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
}
Copy the code

Parameter binding (param_bind/product.go) :

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

Also bind the validator:

// Bind the validatorif v, ok := binding.Validator.Engine().(*validator.Validate); ok {
	v.RegisterValidation("NameValid", param_verify.NameValid)
}
Copy the code

Postman = Postman; Postman = Postman; Postman = Postman; Postman = Postman; Postman = Postman

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

Name = admin:

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

OK, both of the above validations are valid!

The output above is in the console, can return a Json structure of data?

Can. Next, let’s formulate the API return structure.

Specify the API return structure

{
    "code": 1,
    "msg": ""."data": null
}
Copy the code

The return structure of the API interface is basically these three fields.

For example, code=1 indicates success and code=-1 indicates failure.

MSG Indicates a prompt message.

Data indicates the data to be returned.

So, how do we implement this in the GIN framework? Well, it’s really easy to just wrap it with the C.Son () method and 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
}
Copy the code

Controller call (controller/product.go) :

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

Postman = Postman; Postman = Postman; Postman = Postman; Postman = Postman; Postman = Postman

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

Name = admin:

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

OK, both of the above validations are valid!

The source address

Github.com/xinliangnot…

Go-gin-api series of articles

  • 1. Initialize the project using Go Modules