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
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...