go gin 框架下的資料解析與繫結
阿新 • • 發佈:2021-06-28
技術概述
本部落格介紹使用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資料
於是,我們可以:
- 將service服務的結構體中的資料與需要從前端獲取的引數一一對應,而刪除掉多餘的資料
- 宣告一個函式用於json資料獲取,解析與繫結,並呼叫相應的服務,將
c *gin.Context
作為方程的引數 - 將service服務的結構體與接收的json進行繫結
- 呼叫service服務處理資料
- 返回結果
下面用一個比較完整的程式片段來闡述具體用法:
-
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
注意事項&最佳實踐
- 一定要在使用service服務的函式中例項化結構體中的介面,不然會報空指標的錯誤
- 注意結構體中的資料型別,嚴格按照介面文件中的資料型別設計,同時,在“json”或“form“屬性中填入相應的”key“值,做到一一對應
- 一定要在接收資料時加入判錯處理
- 最好不要在一個函式中呼叫兩個service服務(實際上也很難做到)
- 返回給前端的結果可以考慮用
http.StatusOK
替代200
總結
gin框架給程式碼的編寫帶來了諸多方便,不僅程式碼簡單友好,並且在程式出錯的情況下也可以通過報錯快速找到解決措施,因為gin的報錯都很詳細,我推薦使用go語言可以多多使用gin框架。
雖然網上gin的官方文件都介紹的比較詳細,但是關於gin的個人教程以及問答帖子在國內的數量比較少,所以有時候出了問題比較難在網上直接找到解決方法。好在gin語法簡單,只要有一定程式設計基礎,應該都能夠獨立解決大部分問題。