哪種源碼做視頻網(wǎng)站好用知乎軟文推廣
云原生學習路線導航頁(持續(xù)更新中)
本文是golang語言學習系列,本篇對Gin框架的基本使用方法進行學習
1.Gin框架是什么
- Gin 是一個 Go (Golang) 編寫的輕量級 http web 框架,運行速度非???#xff0c;如果你是性能和高效的追求者
- Gin 最擅長的就是 Api 接口的高并發(fā),如果項目的規(guī)模不大,業(yè)務相對簡單,這個時候我們也推薦您使用 Gin
- Gin 的官網(wǎng):https://gin-gonic.com/zh-cn/
- Gin 官方文檔地址:https://gin-gonic.com/zh-cn/docs/
- 有中文文檔,可以直接看文檔學習
- Github 地址:https://github.com/gin-gonic/gin
2.Gin框架快速入門
2.1.快速入門
- 有一篇博客寫的非常詳細,直接看這個入門就行
- Golang gin框架
- 按照上面博客學習過程中,可能遇到的疑問,寫在 2.2 中
2.2.學習上面博客可能遇到的問題
2.2.1.Json和JsonP的區(qū)別
- JSON(JavaScript Object Notation)和JSONP(JSON with Padding)是兩種用于在網(wǎng)絡上傳輸數(shù)據(jù)的格式,二者區(qū)別如下。
- JSON(JavaScript Object Notation)
- JSON 是一種數(shù)據(jù)格式,用于在不同的系統(tǒng)之間傳輸數(shù)據(jù)。
- JSON 是純文本,易于閱讀和編寫,也易于解析和生成。
- JSON 數(shù)據(jù)可以表示為對象、數(shù)組、字符串、數(shù)字、布爾值和 null。
- JSON 數(shù)據(jù)格式不支持跨域請求。
- JSONP(JSON with Padding)
- JSONP 是 JSON 的一種“使用模式”,用于解決跨域請求的問題。
- JSONP 實際上是在 JSON 數(shù)據(jù)周圍包裹了一個函數(shù)調(diào)用,這個函數(shù)名由客戶端指定。
- JSONP的請求,客戶端需要在url后使用
?
指定一個callback
查詢參數(shù) - 因此,在上面的博客中,jsonp請求的響應,會被客戶端傳入的callback包裹起來,形成callback調(diào)用
- JSONP的請求,客戶端需要在url后使用
- JSONP 的工作原理是通過動態(tài)創(chuàng)建
<script>
標簽,將請求發(fā)送到另一個域上的 JSONP 服務端點,并且該服務端點返回的數(shù)據(jù)已經(jīng)包含在了指定的函數(shù)調(diào)用中。 - JSONP 允許在不同域之間進行數(shù)據(jù)交換,繞過了瀏覽器的同源策略限制。
- 總結(jié)
- JSON 是一種數(shù)據(jù)格式,而 JSONP 則是使用 JSON 數(shù)據(jù)進行跨域請求的一種技術
- JSONP 通常用于處理由瀏覽器的同源策略引起的限制,允許在不同域之間進行數(shù)據(jù)交換
2.2.2.HTML模板渲染講的不清楚
- html渲染,上面博客說的不清楚,建議看官方文檔:
- https://gin-gonic.com/zh-cn/docs/examples/html-rendering/
2.2.3.請求參數(shù)綁定結(jié)構(gòu)體重點
-
標記的使用
url后使用?傳遞的查詢參數(shù)
、請求體為"user=123&password=456"這種格式的body
,需要結(jié)構(gòu)體設置 form 才可以使用 gin 的自動綁定type Userinfo struct {Username string `form:"user"`Password string `form:"password"` }
- 不過現(xiàn)在的post請求,請求體為 “application/json”,結(jié)構(gòu)體設置json標記可選
// 設置json,需要按照json標記來,可以綁定 {"user": "123", "pwd": "456"} type Userinfo struct {Username string `json:"user"`Password string `json:"pwd"` }// 沒有設置json,則請求體需要和屬性名一致,可以綁定 {"username": "123", "password": "456"} type Userinfo struct {Username string `form:"user"`Password string `form:"pwd"` }
- 路徑參數(shù),需要使用uri參數(shù)
// 接口可以是 */:user/:pwd type Userinfo struct {Username string `uri:"user"`Password string `uri:"pwd"` }
- Header 頭信息綁定,需要使用header參數(shù)
-
gin.Context 的綁定方法使用
- 我們用的最多的綁定方法是
c.ShouldBind()
,可以根據(jù)req的Context-Type自動推斷要綁定的類型 - 不過 gin.Context 為 很多類型編寫了綁定方法,如果你明確知道前端穿過來的數(shù)據(jù)是什么格式,可以直接使用這些方法
- 可以看到,gin.Context有兩個系列方法,Bindxxx和ShouldBindxxx方法,二者區(qū)別如下
- Bind 系列方法:
- Bind系列方法在綁定失敗時會直接將錯誤信息發(fā)送給客戶端,并終止請求處理。
- 這意味著如果綁定失敗,客戶端將收到一個包含錯誤信息的響應,并且請求處理將不會繼續(xù)進行。
- ShouldBind 系列方法:
- ShouldBind系列方法在綁定失敗時不會立即將錯誤信息發(fā)送給客戶端,而是將錯誤信息存儲在上下文中。
- 這使得開發(fā)者可以根據(jù)實際情況自定義錯誤處理邏輯,例如返回特定的錯誤響應、記錄錯誤日志等。
- 開發(fā)者可以通過檢查上下文中的錯誤信息來判斷綁定是否成功,并根據(jù)需要采取進一步的行動。
- Bind 系列方法:
- 我們用的最多的綁定方法是
-
更詳細的用法,可以學習:
- Gin 框架學習筆記(02)— 參數(shù)自動綁定到結(jié)構(gòu)體
- Go學習第十五章——Gin參數(shù)綁定bind與驗證器
2.2.4.gin.Context.Abort()方法
- gin路由注冊時,參數(shù)可以填多個中間件+一個處理函數(shù)
- 其中參數(shù)位置,gin的中間件,必須放在 處理函數(shù) 前面
- gin的中間件,使用
c.Next
控制是請求到達時執(zhí)行,還是請求返回時執(zhí)行
c.Abort
執(zhí)行后- 當前中間件的后續(xù)語句,還會執(zhí)行
- 但是
c.Next
失效了,后面的中間件和最后的處理函數(shù),都不會再執(zhí)行 - 執(zhí)行完當前中間件,請求就返回了
- 如下面代碼,程序會輸出
1111111111
和handle time
,但是不會輸出2222222222
func CalTimeMiddleWare(c *gin.Context) {start := time.Now()c.Abort()log.Info("1111111111")c.Next()log.Infof("handle time is [%d]", time.Since(start).Nanoseconds()) }func MiddleWare2(c *gin.Context) {log.Info("2222222222") }adminRouter.GET("/users", middleware.CalTimeMiddleWare, middleware.MiddleWare2, controller.NewAdminController().List)
2.2.5.使用gin進行文件上傳
- 上面的博客里,沒有寫gin上傳文件的內(nèi)容
- 可以直接看 官方文檔的內(nèi)容,寫的很詳細
- 上傳單文件:
- https://gin-gonic.com/zh-cn/docs/examples/upload-file/single-file/
- 上傳多文件:
- https://gin-gonic.com/zh-cn/docs/examples/upload-file/multiple-file/
2.2.6.gin獲取cookie
- gin.Context.Cookie(“key1”)方法,獲取cookie中鍵為key1的值
- 比如下面,c.Cookie(“key1”) 得到的值就是 value1
curl --location 'http://localhost:8080/admin/users' \ --header 'Cookie: key1=value1; key2=value2'
- go代碼寫法
v, err := c.Cookie("key1") if err != nil {log.Warnf("don't find cookie in [%s]", c.Request.URL.Path) } c.Set("key1", v)