1. 數據渲染
1.1 各種數據格式的響應
- json、結構體、XML、YAML類似于java的properties、ProtoBuf
1.1.1 返回JSON
package mainimport ("github.com/gin-gonic/gin""net/http"
)func main() {r := gin.Default()r.POST("/demo", func(res *gin.Context) {res.JSON(http.StatusOK, gin.H{"message": "success",})})r.Run(":8080")
}
1.1.2 返回結構體
r.GET("/demo", func(res *gin.Context) {var obj struct {name stringage int8}obj.age = 1obj.name = "張三"res.JSON(http.StatusOK, obj)
})
1.1.3 XML 和 YAML
// 3.XML
r.GET("/someXML", func(c *gin.Context) {c.XML(200, gin.H{"message": "abc"})
})
// 4.YAML響應
r.GET("/someYAML", func(c *gin.Context) {c.YAML(200, gin.H{"name": "zhangsan"})
})
1.1.4 淺淺扒一下源碼
進入res.JSON函數里面看一下
res.JSON(http.StatusOK, obj)
func (c *Context) JSON(code int, obj any) {c.Render(code, render.JSON{Data: obj})
}
- (c *Context) 代表可以被Context類型調用
- (code int, obj any) 傳入參數,狀態碼和返回對象
它本身內部再次封裝了一層提供給Render類型
func (c *Context) Render(code int, r render.Render) {c.Status(code)if !bodyAllowedForStatus(code) {r.WriteContentType(c.Writer)c.Writer.WriteHeaderNow()return}if err := r.Render(c.Writer); err != nil {// Pushing error to c.Errors_ = c.Error(err)c.Abort()}
}
進入Render里面,可以看到
- (code int, r render.Render) 參數進行了更改,傳入了render包下的Render類型
可以看一下Render這個接口
type Render interface {// Render writes data with custom ContentType.Render(http.ResponseWriter) error// WriteContentType writes custom ContentType.WriteContentType(w http.ResponseWriter)
}
接口還提供了一個可以修改ContentType的方法
if !bodyAllowedForStatus(code) {r.WriteContentType(c.Writer)c.Writer.WriteHeaderNow()return
}
- bodyAllowedForStatus()進行了判斷
func bodyAllowedForStatus(status int) bool {switch {case status >= 100 && status <= 199:return falsecase status == http.StatusNoContent:return falsecase status == http.StatusNotModified:return false}return true
}
判斷了傳入的狀態碼是否符合正確的狀態碼,并返回
-
當bodyAllowedForStatus()判斷為錯誤狀態碼時
會在返回對象中寫入ContentType內容
? c.Writer.WriteHeaderNow()還會寫入文本流中
再看一下其他返回的類型;例如XML
func (c *Context) XML(code int, obj any) {c.Render(code, render.XML{Data: obj})
}
在內部封裝時,只是標注了不同的render類型
1.2 重定向
訪問/demo地址時,將頁面重定向跳轉至其他頁面
package mainimport ("github.com/gin-gonic/gin""net/http"
)func main() {r := gin.Default()r.GET("/demo", func(c *gin.Context) {c.Redirect(http.StatusMovedPermanently, "http://www.baidu.com")})r.Run(":8080")
}
2. 中間件
2.1 全局中間件
- 所有請求都經過此中間件
package mainimport ("github.com/gin-gonic/gin""log""time"
)func MiddleWare() gin.HandlerFunc {return func(c *gin.Context) {t := time.Now()log.Println("中間件開始運行:", t)c.Set("middle_1", "中間件1執行結束")status := c.Writer.Status()log.Println("中間件執行結束:", status)t2 := time.Since(t)log.Println("耗時:", t2)}
}func main() {r := gin.Default()// 注冊中間件r.Use(MiddleWare())r.GET("/demo", func(c *gin.Context) {// 獲得內容m, _ := c.Get("middle_1")log.Println("中間件接收參數:", m)c.JSON(200, gin.H{"中間件接收參數:": m})})r.Run(":8080")
}
測試:http://localhost:8080/demo
返回結果:
[GIN-debug] Listening and serving HTTP on :8080
2025/04/29 00:12:34 中間件開始運行: 2025-04-29 00:12:34.5992889 +0800 CST m=+1.770059901
2025/04/29 00:12:34 中間件執行結束: 200
2025/04/29 00:12:34 耗時: 11.5258ms
2025/04/29 00:12:34 中間件接收參數: 中間件1執行結束
[GIN] 2025/04/29 - 00:12:34 | 200 | 11.5258ms | ::1 | GET "/demo"
gin 使用r.Use()來注冊一個組件
- 在注冊組件時,我們需要規定函數的返回類型,這才能讓gin知道這是什么組件
func MiddleWare() gin.HandlerFunc {return func(c *gin.Context) {t := time.Now()log.Println("中間件開始運行:", t)c.Set("middle_1", "中間件1執行結束")status := c.Writer.Status()log.Println("中間件執行結束:", status)t2 := time.Since(t)log.Println("耗時:", t2)}
}
- 這里MiddleWare()函數規定了返回類型是
gin.HandlerFunc
,這就代表這個函數是一個處理類
2.1.1 Next() 方法
我們在正常注冊中間件時,會打斷原有的運行流程,但是你可以在中間件函數內部添加Next()方法,這樣可以讓原有的運行流程繼續執行,當原有的運行流程結束后再回來執行中間件內部的內容
package mainimport ("github.com/gin-gonic/gin""log""time"
)func MiddleWare() gin.HandlerFunc {return func(c *gin.Context) {t := time.Now()log.Println("中間件開始運行:", t)// 開啟正常執行流程c.Next()c.Set("middle_1", "中間件1執行結束")status := c.Writer.Status()log.Println("中間件執行結束:", status)t2 := time.Since(t)log.Println("耗時:", t2)}
}func main() {r := gin.Default()// 注冊中間件r.Use(MiddleWare())r.GET("/demo", func(c *gin.Context) {// 獲得內容m, _ := c.Get("middle_1")log.Println("中間件接收參數:", m)c.JSON(200, gin.H{"中間件接收參數:": m})})r.Run(":8080")
}
測試:http://localhost:8080/demo
返回結果:
[GIN-debug] Listening and serving HTTP on :8080
2025/04/29 00:14:14 中間件開始運行: 2025-04-29 00:14:14.5697461 +0800 CST m=+2.981609901
2025/04/29 00:14:14 中間件接收參數: <nil>
2025/04/29 00:14:14 中間件執行結束: 200
2025/04/29 00:14:14 耗時: 14.0262ms
[GIN] 2025/04/29 - 00:14:14 | 200 | 14.0262ms | ::1 | GET "/demo"
可以看到使用next后,正常執行流程中并沒有獲得到中間件設置的值
2.2 局部中間件
package mainimport ("github.com/gin-gonic/gin""log""time"
)func MiddleWare() gin.HandlerFunc {return func(c *gin.Context) {t := time.Now()log.Println("中間件開始運行:", t)c.Set("middle_1", "中間件1執行結束")status := c.Writer.Status()log.Println("中間件執行結束:", status)t2 := time.Since(t)log.Println("耗時:", t2)}
}func main() {r := gin.Default()// 局部中間件-在為一個請求添加執行函數時即可掛載中間件r.GET("/demo", MiddleWare(), func(c *gin.Context) {// 獲得內容m, _ := c.Get("middle_1")log.Println("中間件接收參數:", m)c.JSON(200, gin.H{"中間件接收參數:": m})})r.Run(":8080")
}
- 為你想給哪一個請求掛載中間件,直接在對應的請求中添加中間件函數即可
3. ??GoGin框架——前文鏈接
Gin框架學習參考網站:gin框架·Go語言中文文檔
- (Go Gin)基于Go的WEB開發框架,GO Gin是什么?怎么啟動?本文給你答案
- (Go Gin)Gin學習筆記(二):路由配置、基本路由、表單參數、上傳單個文件、上傳多個文件、淺扒路由原理
(Go Gin)Gin學習筆記(三):數據解析和綁定,結構體分析,包括JSON解析、form解析、URL解析,區分綁定的Bind方法
4. 💕👉博客專欄
- Golang專欄-包含基礎、Gin、Goam等知識
- 云原生專欄-包含k8s、docker等知識
- 從0開始學習云計算-華為HCIP證書
- JUC專欄-帶你快速領悟JUC的知識!
- JVM專欄-深入Java虛擬機,理解JVM的原理
- 基于Java研究 數據結構與算法-包含貪心算法、加權圖、最短路徑算法等知識
- Docker專欄-上手熱門容器技術Docker
- SpringBoot專欄-學習SpringBoot快速開發后端
- 項目管理工具的學習-設計技術:Maven、Git、Gradle等相關管理工具
- JavaSE-全面了解Java基礎
- JS專欄-使用JS作的一部分實例~
- 使用CSS所作的一部分案例