深入理解 Go 語言 Gin 框架的請求處理機制
一、獲取 GET 請求
1、URL?參數
- http://127.0.0.1:8080/user/search?username=snail&address=sh
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
//Default返回一個默認的路由引擎
r := gin.Default()
r.GET("/user/search", func(c *gin.Context) {
username := c.DefaultQuery("username", "snail")
//username := c.Query("username")
address := c.Query("address")
//輸出json結果給調用方
c.JSON(http.StatusOK, gin.H{
"message": "ok",
"username": username,
"address": address,
})
})
r.Run()
}
2、url 中 path 參數
-
可以通過 Context 的 Param 方法來獲取 API 參數
-
localhost:8000/xxx/snail
package main
import (
"github.com/gin-gonic/gin"
"net/http"
"strings"
)
func main() {
r := gin.Default()
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+" blog: "+action)
})
//默認爲監聽8080端口
r.Run(":8000")
}
二、獲取 form 參數
1、main.go
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
r.POST("/form", func(c *gin.Context) {
types := c.DefaultPostForm("type", "post")
username := c.PostForm("username")
password := c.PostForm("userpassword")
// c.String(http.StatusOK, fmt.Sprintf("username:%s,password:%s,type:%s", username, password, types))
c.String(http.StatusOK, fmt.Sprintf("username:%s,password:%s,type:%s", username, password, types))
})
r.Run()
}
2、form.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta >
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form action="http://localhost:8080/form" method="post" action="application/x-www-form-urlencoded">
用戶名:<input type="text" > <br>
密 碼:<input type="password" > <br>
<input type="submit" value="提交">
</form>
</body>
</html>
3、演示效果
三、獲取 json 參數
1、獲取 json 參數
package main
import (
"encoding/json"
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
//Default返回一個默認的路由引擎
r := gin.Default()
r.POST("/json", func(c *gin.Context) {
// 注意:下面爲了舉例子方便,暫時忽略了錯誤處理
b, _ := c.GetRawData() // 從c.Request.Body讀取請求數據
// 定義map或結構體
var m map[string]interface{}
// 反序列化
_ = json.Unmarshal(b, &m)
c.JSON(http.StatusOK, m)
})
r.Run()
}
2、postman 測試
四、ShouldBind 參數綁定
-
我們可以基於請求的 content-Type 識別請求數據類型並利用反射機制
-
自動提取請求中 QueryString、form 表單、JSON、XML 等參數到結構體中
-
下面的示例代碼演示了. ShouldBind() 強大的功能
-
它能夠基於請求自動提取 JSON、form 表單和 QueryString 類型的數據,並把值綁定到指定的結構體對象
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
)
// Binding from JSON
type Login struct {
User string `form:"user" json:"user" binding:"required"`
Password string `form:"password" json:"password" binding:"required"`
}
func main() {
router := gin.Default()
// 綁定JSON的示例 ({"user": "zhangsan", "password": "123456"})
router.POST("/loginJSON", func(c *gin.Context) {
var login Login
if err := c.ShouldBind(&login); err == nil {
fmt.Printf("login info:%#v\n", login)
c.JSON(http.StatusOK, gin.H{
"user": login.User,
"password": login.Password,
})
} else {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}
})
// 綁定form表單示例 (user=zhangsan&password=123456)
router.POST("/loginForm", func(c *gin.Context) {
var login Login
// ShouldBind()會根據請求的Content-Type自行選擇綁定器
if err := c.ShouldBind(&login); err == nil {
c.JSON(http.StatusOK, gin.H{
"user": login.User,
"password": login.Password,
})
} else {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}
})
// 綁定QueryString示例 (/loginForm?user=zhangsan&password=123456)
router.GET("/loginForm", func(c *gin.Context) {
var login Login
// ShouldBind()會根據請求的Content-Type自行選擇綁定器
if err := c.ShouldBind(&login); err == nil {
c.JSON(http.StatusOK, gin.H{
"user": login.User,
"password": login.Password,
})
} else {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}
})
// Listen and serve on 0.0.0.0:8080
router.Run(":8080")
}
五、獲取單個文件
-
multipart/form-data 格式用於文件上傳
-
gin 文件上傳與原生的 net/http 方法類似,不同在於 gin 把原生的 request 封裝到 c.Request 中
1、main.go
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
//限制上傳最大尺寸
r.MaxMultipartMemory = 8 << 20
r.POST("/upload", func(c *gin.Context) {
file, err := c.FormFile("file")
if err != nil {
c.String(500, "上傳圖片出錯")
}
// c.JSON(200, gin.H{"message": file.Header.Context})
c.SaveUploadedFile(file, file.Filename)
c.String(http.StatusOK, file.Filename)
})
r.Run()
}
2、upload.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta >
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form action="http://localhost:8080/upload" method="post" enctype="multipart/form-data">
上傳文件:<input type="file" >
<input type="submit" value="提交">
</form>
</body>
</html>
3、上傳特定文件
-
有的用戶上傳文件需要限制上傳文件的類型以及上傳文件的大小
-
但是 gin 框架暫時沒有這些函數 (也有可能是我沒找到)
-
因此基於原生的函數寫法自己寫了一個可以限制大小以及文件類型的上傳函數
package main
import (
"fmt"
"log"
"net/http"
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.POST("/upload", func(c *gin.Context) {
_, headers, err := c.Request.FormFile("file")
if err != nil {
log.Printf("Error when try to get file: %v", err)
}
//headers.Size 獲取文件大小
if headers.Size > 1024*1024*2 {
fmt.Println("文件太大了")
return
}
//headers.Header.Get("Content-Type")獲取上傳文件的類型
if headers.Header.Get("Content-Type") != "image/png" {
fmt.Println("只允許上傳png圖片")
return
}
c.SaveUploadedFile(headers, "./video/"+headers.Filename)
c.String(http.StatusOK, headers.Filname)
})
r.Run()
}
六、獲取多個文件
1、main.go
package main
import (
"github.com/gin-gonic/gin"
"net/http"
"fmt"
)
// gin的helloWorld
func main() {
// 1.創建路由
// 默認使用了2箇中間件Logger(), Recovery()
r := gin.Default()
// 限制表單上傳大小 8MB,默認爲32MB
r.MaxMultipartMemory = 8 << 20
r.POST("/upload", func(c *gin.Context) {
form, err := c.MultipartForm()
if err != nil {
c.String(http.StatusBadRequest, fmt.Sprintf("get err %s", err.Error()))
}
// 獲取所有圖片
files := form.File["files"]
// 遍歷所有圖片
for _, file := range files {
// 逐個存
if err := c.SaveUploadedFile(file, file.Filename); err != nil {
c.String(http.StatusBadRequest, fmt.Sprintf("upload err %s", err.Error()))
return
}
}
c.String(200, fmt.Sprintf("upload ok %d files", len(files)))
})
//默認端口號是8080
r.Run(":8000")
}
2、upload.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta >
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<form action="http://localhost:8000/upload" method="post" enctype="multipart/form-data">
上傳文件:<input type="file" multiple>
<input type="submit" value="提交">
</form>
</body>
</html>
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/AzfCL5Uy283H1ltedlgdsw