Gin框架 - 數據綁定和驗證

来源:https://www.cnblogs.com/it-3327/archive/2019/11/14/11863070.html
-Advertisement-
Play Games

概述上篇文章分享了 Gin 框架使用 Logrus 進行日誌記錄,這篇文章分享 Gin 框架的數據綁定與驗證。有讀者咨詢我一個問題,如何讓框架的運行日誌不輸出控制台?解決方案: engine := gin.Default() //修改成如下 engine := gin.New() 我是怎麼知道的?看 ...


概述

上篇文章分享了 Gin 框架使用 Logrus 進行日誌記錄,這篇文章分享 Gin 框架的數據綁定與驗證。

有讀者咨詢我一個問題,如何讓框架的運行日誌不輸出控制台?

解決方案:

   

engine := gin.Default() //修改成如下    
    engine := gin.New() 

 



我是怎麼知道的?看框架代碼。

Default():

    func Default() *Engine {    
        debugPrintWARNINGDefault()    
        engine := New()    
        engine.Use(Logger(), Recovery())    
        return engine    
    }

 



New() 代碼我就不貼了。

我們看到 Default() 使用了兩個中間件 Logger(),Recovery(),如果不想使用,那就直接使用 New() 就可以了。

開始今天的文章。

比如,請求 v1/member/add 新增會員方法, name、 age 為必填,同時 name 不能等於 admin 字元串,10 <= age <= 120。

直接看代碼吧。

首先,先定義一個結構體。

entity/member.go

    package entity    
    // 定義 Member 結構體    
    type Member struct {    
        Name string `form:"name" json:"name" binding:"required,NameValid"`    
        Age  int    `form:"age"  json:"age"  binding:"required,gt=10,lt=120"`    
    }

 


binding 中 required,這個是框架自帶的, NameValid,這個是自己定義的。

問題一:框架自帶的 binding 參數還有哪些?

問題二:自定義驗證方法,怎麼寫?

接下來要說的就是問題二,寫一個驗證方法。

validator/member/member.go

    package member    
    import (    
        "gopkg.in/go-playground/validator.v8"    
        "reflect"    
    )    
    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    
    }

 



接下來,在路由中綁定:

router/router.go

    package router    
    import (    
        "ginDemo/middleware/logger"    
        "ginDemo/middleware/sign"    
        "ginDemo/router/v1"    
        "ginDemo/router/v2"    
        "ginDemo/validator/member"    
        "github.com/gin-gonic/gin"    
        "github.com/gin-gonic/gin/binding"    
        "gopkg.in/go-playground/validator.v8"    
    )    
    func InitRouter(r *gin.Engine)  {    
        r.Use(logger.LoggerToFile())    
        // v1 版本    
        GroupV1 := r.Group("/v1")    
        {    
            GroupV1.Any("/product/add", v1.AddProduct)    
            GroupV1.Any("/member/add", v1.AddMember)    
        }    
        // v2 版本    
        GroupV2 := r.Group("/v2").Use(sign.Sign())    
        {    
            GroupV2.Any("/product/add", v2.AddProduct)    
            GroupV2.Any("/member/add", v2.AddMember)    
        }    
        // 綁定驗證器    
        if v, ok := binding.Validator.Engine().(*validator.Validate); ok {    
            v.RegisterValidation("NameValid", member.NameValid)    
        }    
    }

 



最後,看一下調用的代碼。

router/v1/member.go

    package v1    
    import (    
        "ginDemo/entity"    
        "github.com/gin-gonic/gin"    
        "net/http"    
    )    
    func AddMember(c *gin.Context) {    
        res := entity.Result{}    
        mem := entity.Member{}    
        if err := c.ShouldBind(&mem); err != nil {    
            res.SetCode(entity.CODE_ERROR)    
            res.SetMessage(err.Error())    
            c.JSON(http.StatusForbidden, res)    
            c.Abort()    
            return    
        }    
        // 處理業務(下次再分享)    
        data := map[string]interface{}{    
            "name" : mem.Name,    
            "age"  : mem.Age,    
        }    
        res.SetCode(entity.CODE_ERROR)    
        res.SetData(data)    
        c.JSON(http.StatusOK, res)    
    }

 


訪問看看效果吧。

訪問:http://localhost:8080/v1/member/add

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

訪問:http://localhost:8080/v1/member/add?name=1

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

訪問:http://localhost:8080/v1/member/add?age=1

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

訪問:http://localhost:8080/v1/member/add?name=admin&age=1

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

訪問:http://localhost:8080/v1/member/add?name=1&age=1

    {    
        "code": -1,    
        "msg": "Key: 'Member.Age' Error:Field validation for 'Age' failed on the 'gt' tag",    
        "data": null    
    }

訪問:http://localhost:8080/v1/member/add?name=1&age=121

    {    
        "code": -1,    
        "msg": "Key: 'Member.Age' Error:Field validation for 'Age' failed on the 'lt' tag",    
        "data": null    
    }

訪問:http://localhost:8080/v1/member/add?name=Tom&age=30

    {    
        "code": 1,    
        "msg": "",    
        "data": {    
            "age": 30,    
            "name": "Tom"    
        }    
}

 


   
為避免返回信息過多,錯誤提示咱們也可以統一。

   

if err := c.ShouldBind(&mem); err != nil {    
        res.SetCode(entity.CODE_ERROR)    
        res.SetMessage("參數驗證錯誤")    
        c.JSON(http.StatusForbidden, res)    
        c.Abort()    
        return    
    }

 



這一次目錄結構調整了一些,在這裡說一下:

    ├─ ginDemo    
    │  ├─ common        //公共方法    
    │     ├── common.go    
    │  ├─ config        //配置文件    
    │     ├── config.go    
    │  ├─ entity        //實體    
    │     ├── ...    
    │  ├─ middleware    //中間件    
    │     ├── logger    
    │         ├── ...    
    │     ├── sign    
    │         ├── ...    
    │  ├─ router        //路由    
    │     ├── ...    
    │  ├─ validator     //驗證器    
    │     ├── ...    
    │  ├─ vendor        //擴展包    
    │     ├── github.com    
    │         ├── ...    
    │     ├── golang.org    
    │         ├── ...    
    │     ├── gopkg.in    
    │         ├── ...    
    │  ├─ Gopkg.toml    
    │  ├─ Gopkg.lock    
    │  ├─ main.go

將 sign 和 logger 調整為中間件,並放到 middleware 中間件 目錄。

新增了 common 公共方法目錄。

新增了 validator 驗證器目錄。

新增了 entity 實體目錄。

具體代碼我會放到 GitHub,有感興趣的可以去看:https://github.com/xinliangnote/Go。

上面還遺漏了 問題一 沒解決,框架自帶的 binding 參數還有哪些?



您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • Selenium是一個自動化測試工具,利用它我們可以驅動瀏覽器執行特定的動作,如點擊、下拉等操作。 本文將從環境部署到項目開發一步步講解,包括這個過程所可能遇到的一些問題,都會一一解答,有不會的問題可以在下方評論留言一起思考解決。 一.環境部署 環境部署包括mac和linux 1.安裝Seleniu ...
  • 上面那些代碼非常不容易理解,我們需要把它拆分來看當我們直接實例化一個類的時候,如果大括弧豎著排,那麼裡面的成員賦值後要加個逗號 定義一個介面,介面裡面有一個成員方法 定義另一個類型,這個類型剛好就有這個方法,那麼就可以認為這個類型實現了介面 這個時候如果定義Flag類型的變數,那麼StringFla ...
  • 1、埠轉發 在虛擬機設置各個資料庫對應的埠轉發 2、修改資料庫配置文件 預設只有本機的IP才可以訪問,其它IP就連不上了,修改bind ip 為0.0.0.0 3、重啟服務(或者直接重啟虛擬機) service mongodb restart ...
  • 常用的高級程式設計語言 常用的高級程式設計語言 語言 特點 FORTRAN 數值計算 COBOL 事務處理 PASCAL 結構化程式設計 LISP 函數式程式設計 PROLOG 邏輯程式設計 C 系統程式設計 Smalltalk 面向對象程式設計 Java Internet應用,可移植性 Pytho ...
  • Lambda表達式 :也可稱為閉包,Lambda允許把函數作為一個方法的參數(函數作為參數傳遞到方法中),免去了使用匿名方法的麻煩,並且給予Java簡單但是強大的函數化的編程能力 ...
  • 對於MySQL而言,其實分為客戶端與服務端。 服務端,就是MySQL應用,當我們使用net start mysql命令啟動的服務,其實就是啟動了MySQL的服務端。 客戶端,負責發送請求到服務端並從服務端獲取數據,客戶端可以有多種形式,可以是我們通過mysql uroot p1234打開的黑視窗,也 ...
  • 面向過程編程 面向過程編程其實是一種 機械式的思維方式 ,其核心就是 "過程" 。 過程指的是 一種解決問題的步驟 ,即先乾什麼再乾什麼,最後乾什麼。 優點 :將複雜的問題流程化,進而簡單化。 哈哈哈哈,這種時刻,話不多說,上代碼! 以上就是實現用戶註冊功能的面向過程思想的代碼的展現。這個時候,如果 ...
  • 在開發職業發展中,想要學習一門新技術,怎麼辦? 最常見的是看文檔,擼代碼,看視頻 分享幾個技術更新及時學習的網站。基本都免費。各位按需使用。 1,黑馬程式員視頻庫 http://yun.itheima.com/ 傳智播客及黑馬程式員視頻庫涵蓋了Java,人工智慧Python,前端,大數據等多方向! ...
一周排行
    -Advertisement-
    Play Games
  • 概述:本文代碼示例演示瞭如何在WPF中使用LiveCharts庫創建動態條形圖。通過創建數據模型、ViewModel和在XAML中使用`CartesianChart`控制項,你可以輕鬆實現圖表的數據綁定和動態更新。我將通過清晰的步驟指南包括詳細的中文註釋,幫助你快速理解並應用這一功能。 先上效果: 在 ...
  • openGauss(GaussDB ) openGauss是一款全面友好開放,攜手伙伴共同打造的企業級開源關係型資料庫。openGauss採用木蘭寬鬆許可證v2發行,提供面向多核架構的極致性能、全鏈路的業務、數據安全、基於AI的調優和高效運維的能力。openGauss深度融合華為在資料庫領域多年的研 ...
  • openGauss(GaussDB ) openGauss是一款全面友好開放,攜手伙伴共同打造的企業級開源關係型資料庫。openGauss採用木蘭寬鬆許可證v2發行,提供面向多核架構的極致性能、全鏈路的業務、數據安全、基於AI的調優和高效運維的能力。openGauss深度融合華為在資料庫領域多年的研 ...
  • 概述:本示例演示了在WPF應用程式中實現多語言支持的詳細步驟。通過資源字典和數據綁定,以及使用語言管理器類,應用程式能夠在運行時動態切換語言。這種方法使得多語言支持更加靈活,便於維護,同時提供清晰的代碼結構。 在WPF中實現多語言的一種常見方法是使用資源字典和數據綁定。以下是一個詳細的步驟和示例源代 ...
  • 描述(做一個簡單的記錄): 事件(event)的本質是一個委托;(聲明一個事件: public event TestDelegate eventTest;) 委托(delegate)可以理解為一個符合某種簽名的方法類型;比如:TestDelegate委托的返回數據類型為string,參數為 int和 ...
  • 1、AOT適合場景 Aot適合工具類型的項目使用,優點禁止反編 ,第一次啟動快,業務型項目或者反射多的項目不適合用AOT AOT更新記錄: 實實在在經過實踐的AOT ORM 5.1.4.117 +支持AOT 5.1.4.123 +支持CodeFirst和非同步方法 5.1.4.129-preview1 ...
  • 總說周知,UWP 是運行在沙盒裡面的,所有許可權都有嚴格限制,和沙盒外交互也需要特殊的通道,所以從根本杜絕了 UWP 毒瘤的存在。但是實際上 UWP 只是一個應用模型,本身是沒有什麼許可權管理的,許可權管理全靠 App Container 沙盒控制,如果我們脫離了這個沙盒,UWP 就會放飛自我了。那麼有沒... ...
  • 目錄條款17:讓介面容易被正確使用,不易被誤用(Make interfaces easy to use correctly and hard to use incorrectly)限制類型和值規定能做和不能做的事提供行為一致的介面條款19:設計class猶如設計type(Treat class de ...
  • title: 從零開始:Django項目的創建與配置指南 date: 2024/5/2 18:29:33 updated: 2024/5/2 18:29:33 categories: 後端開發 tags: Django WebDev Python ORM Security Deployment Op ...
  • 1、BOM對象 BOM:Broswer object model,即瀏覽器提供我們開發者在javascript用於操作瀏覽器的對象。 1.1、window對象 視窗方法 // BOM Browser object model 瀏覽器對象模型 // js中最大的一個對象.整個瀏覽器視窗出現的所有東西都 ...