1. 程式人生 > 其它 >go gin 框架下的資料解析與繫結

go gin 框架下的資料解析與繫結

技術概述

本部落格介紹使用gin框架完成基礎的資料解析與繫結功能,以及列舉出一些比較容易踩的坑。主要內容包括:json資料解析與繫結,表單資料解析與繫結,url資料解析與繫結

技術詳述

1. json資料解析與繫結

先看官方文件中的原始碼:

// 定義接收資料的結構體
type Login struct {
   User    string `form:"username" json:"user" uri:"user" xml:"user" binding:"required"`
   Pssword string `form:"password" json:"password" uri:"password" xml:"password" binding:"required"`
}

func main() {
   r := gin.Default()
   // JSON繫結
   r.POST("loginJSON", func(c *gin.Context) {
      var json Login
      // 將request的body中的資料,自動按照json格式解析到結構體
      if err := c.ShouldBindJSON(&json); err != nil {
         // 返回錯誤資訊
         // gin.H封裝了生成json資料的工具
         c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
         return
      }
      // 判斷使用者名稱密碼是否正確
      if json.User != "root" || json.Pssword != "admin" {
         c.JSON(http.StatusBadRequest, gin.H{"status": "304"})
         return
      }
      c.JSON(http.StatusOK, gin.H{"status": "200"})
   })
   r.Run(":8000")
}

這是一個簡單的獲取json中的賬號密碼,並進行驗證的例子。從該例子中可以看出:

  • 獲取json資料時不必通過輸入json中每個key值來獲得對應的資料
  • 結構體需要與獲取json的格式相對應
  • 返回結果可以使用gin框架中封裝的方法
  • post方法中需要一個與上下文(context)有關的引數,用於接收前端發來的json資料

於是,我們可以:

  1. 將service服務的結構體中的資料與需要從前端獲取的引數一一對應,而刪除掉多餘的資料
  2. 宣告一個函式用於json資料獲取,解析與繫結,並呼叫相應的服務,將 c *gin.Context作為方程的引數
  3. 將service服務的結構體與接收的json進行繫結
  4. 呼叫service服務處理資料
  5. 返回結果

下面用一個比較完整的程式片段來闡述具體用法:

  • service結構體中的資料

    type CreateTeamService struct {
    	model.TeamRepositoryInterface // 聲明瞭具體操作資料庫建立團隊的介面
    	Name          string `form:"name" json:"name" binding:"required"`
    	GroupLeaderID int    `form:"group_leader_id" json:"group_leader_id" binding:"required"`
    	ClassID       int    `form:"class_id" json:"class_id" binding:"required"`
    }
    
  • post方法響應請求

    	// 建立團隊
    	v1.POST("team/create", api.CreateTeam)
    
  • json資料解析與繫結具體函式

    func CreateTeam(c *gin.Context) { // 該函式與CreateTeamService服務在不同的檔案中
    	var service service.CreateTeamService
    	if err := c.ShouldBind(&service); err == nil {
            // 例項化介面
    		service.TeamRepositoryInterface = &model.Repo
    		res := service.CreateTeam()
    		c.JSON(http.StatusOK, res)
    	} else {
    		c.JSON(http.StatusOK, ErrorResponse(err))
    	}
    }
    

可以看出,大致過程與上述官方文件中的用例一致。

2. 表單資料解析和繫結

具體程式碼與json資料解析與繫結幾乎完全一致,不同處僅僅在於將ShouldBindJSON()方法換成了Bind()方法。

這也是gin框架的強大之處,即面對不同的前端資料有統一的程式碼處理方法。其本質上,還是將表單資料中每個資料的key值與結構中的資料一一對應。

  • 表單結構示例

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
    </head>
    <body>
        <form action="http://localhost:8000/loginForm" method="post" enctype="application/x-www-form-urlencoded">
            使用者名稱<input type="text" name="username"><br>
            密碼<input type="password" name="password">
            <input type="submit" value="提交">
        </form>
    </body>
    </html>
    
  • 結構體示例

    type Login struct {
        // binding:"required"修飾的欄位,若接收為空值,則報錯,是必須欄位
        User    string `form:"username" json:"user" uri:"user" xml:"user" binding:"required"`
        Pssword string `form:"password" json:"password" uri:"password" xml:"password" binding:"required"`
    }
    

3. URI資料解析和繫結

具體程式碼與上述兩種方式大致相同,同樣地,需要將ShouldBindJSON()方法換成ShouldBindUri方法。

除此之外,需要注意獲取api引數的方法,在此僅介紹最簡單的一種方法:

  • 獲取api引數程式碼

    (測試url:localhost:8080/user/烏雞/805376577.com

     r.GET("/user/:name/*action", func(c *gin.Context) {
            name := c.Param("name")
            action := c.Param("action")
            //擷取/
            action = strings.Trim(action, "/")
            c.String(http.StatusOK, name+" is "+action)
        })
    

輸出結果:烏雞 is 805376577.com

注意事項&最佳實踐

  1. 一定要在使用service服務的函式中例項化結構體中的介面,不然會報空指標的錯誤
  2. 注意結構體中的資料型別,嚴格按照介面文件中的資料型別設計,同時,在“json”或“form“屬性中填入相應的”key“值,做到一一對應
  3. 一定要在接收資料時加入判錯處理
  4. 最好不要在一個函式中呼叫兩個service服務(實際上也很難做到)
  5. 返回給前端的結果可以考慮用http.StatusOK替代200

總結

gin框架給程式碼的編寫帶來了諸多方便,不僅程式碼簡單友好,並且在程式出錯的情況下也可以通過報錯快速找到解決措施,因為gin的報錯都很詳細,我推薦使用go語言可以多多使用gin框架。

雖然網上gin的官方文件都介紹的比較詳細,但是關於gin的個人教程以及問答帖子在國內的數量比較少,所以有時候出了問題比較難在網上直接找到解決方法。好在gin語法簡單,只要有一定程式設計基礎,應該都能夠獨立解決大部分問題。

參考文件

http://www.topgoer.com/gin框架/gin路由/api引數.html