概述
首先同步下項目概況:
上篇文章分享了,使用 go modules 初始化項目,這篇文章我們分享:
規劃目錄結構
模型綁定和驗證
自定義驗證器
制定 API 返回結構
廢話很少說,我們開始吧。
規劃目錄結構
php
├─ 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 //入口文件
上面的目錄結構是我自定義的,你們也能夠根據本身的習慣去定義。
controller 控制器層主要對提交過來的數據進行驗證,而後將驗證完成的數據傳遞給 service 處理。
在 gin 框架中,參數驗證有兩種:
一、模型綁定和驗證。
二、自定義驗證器。
其中目錄 param_bind,存儲的是參數綁定的數據,目錄 param_verify 存儲的是自定義驗證器。
接下來,讓我們進行簡單實現。
模型綁定和驗證
好比,有一個建立商品的接口,商品名稱不能爲空。
配置路由(route.go):
git
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) }
參數綁定(param_bind/product.go):
github
type ProductAdd struct { Name string `form:"name" json:"name" binding:"required"` }
控制器調用(controller/product.go):
數據庫
if err := c.ShouldBind(¶m_bind.ProductAdd{}); err != nil { utilGin.Response(-1, err.Error(), nil) return }
我們用 Postman 模擬 post 請求時,name 參數不傳或傳遞爲空,會出現:
Key: 'ProductAdd.Name' Error:Field validation for 'Name' failed on the 'required' tag
這說明使用到了參數設置的 binding:"required"。
那麼還能使用 binding 哪些參數,有文檔嗎?
有。Gin 使用 go-playground/validator.v8 進行驗證,相關文檔:
https://godoc.org/gopkg.in/go-playground/validator.v8
接下來,我們實現一下自定義驗證器。
自定義驗證器
好比,有一個建立商品的接口,商品名稱不能爲空而且參數名稱不能等於 admin。
相似於這種業務需求,沒法 binding 現成的方法,須要咱們本身寫驗證方法,才能實現。
自定義驗證方法(param_verify/product.go)
json
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 }
參數綁定(param_bind/product.go):
api
type ProductAdd struct { Name string `form:"name" json:"name" binding:"required,NameValid"` }
同時還要綁定驗證器:
app
// 綁定驗證器 if v, ok := binding.Validator.Engine().(*validator.Validate); ok { v.RegisterValidation("NameValid", param_verify.NameValid) }
我們用 Postman 模擬 post 請求時,name 參數不傳或傳遞爲空,會出現:
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,上面兩個驗證都生效了!
上面的輸出都是在控制檯,能不能返回一個 Json 結構的數據呀?
能。接下來我們制定 API 返回結構。
制定 API 返回結構
框架
{ "code": 1, "msg": "", "data": null }
API 接口的返回的結構基本都是這三個字段。
好比 code=1 表示成功,code=-1 表示失敗。
msg 表示提示信息。
data 表示返回的數據。
那麼,咱們怎麼在 gin 框架中實現它?
其實很簡單 基於 c.JSON() 方法進行封裝便可,直接看代碼。
工具
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 }
控制器調用(controller/product.go):
post
utilGin := util.Gin{Ctx:c} if err := c.ShouldBind(¶m_bind.ProductAdd{}); err != nil { utilGin.Response(-1, err.Error(), nil) return }
我們用 Postman 模擬 post 請求時,name 參數不傳或傳遞爲空,會出現:
{ "code": -1, "msg": "Key: 'ProductAdd.Name' Error:Field validation for 'Name' failed on the 'required' tag", "data": null }
name=admin 時: { "code": -1, "msg": "Key: 'ProductAdd.Name' Error:Field validation for 'Name' failed on the 'NameValid' tag", "data": null }
OK,上面兩個驗證都生效了!