URI 绑定可以把路径参数直接绑定到结构体,代码更清晰。
type UserParams struct {
ID string `uri:"id" binding:"required"`
}
r.GET("/users/:id", func(c *gin.Context) {
var params UserParams
if err := c.ShouldBindUri(¶ms); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{"user_id": params.ID})
})
访问 /users/123,ID 的值是 123。
type PostParams struct {
UserID string `uri:"user_id" binding:"required"`
PostID string `uri:"post_id" binding:"required"`
}
r.GET("/users/:user_id/posts/:post_id", func(c *gin.Context) {
var params PostParams
if err := c.ShouldBindUri(¶ms); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{
"user_id": params.UserID,
"post_id": params.PostID,
})
})
访问 /users/123/posts/456,得到 user_id=123 和 post_id=456。
import "strconv"
type UserParams struct {
ID int `uri:"id" binding:"required,gt=0"`
}
r.GET("/users/:id", func(c *gin.Context) {
var params UserParams
if err := c.ShouldBindUri(¶ms); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{"user_id": params.ID})
})
访问 /users/abc 会返回错误,因为 abc 无法转换为 int。
type FileParams struct {
Path string `uri:"path"`
}
r.GET("/files/*path", func(c *gin.Context) {
var params FileParams
if err := c.ShouldBindUri(¶ms); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{"path": params.Path})
})
访问 /files/docs/report.pdf,Path 的值是 /docs/report.pdf。
URI 绑定可以和其他绑定组合使用:
type UpdateUserParams struct {
ID string `uri:"id" binding:"required"`
Name string `json:"name" binding:"required"`
}
r.PUT("/users/:id", func(c *gin.Context) {
var params UpdateUserParams
if err := c.ShouldBindUri(¶ms); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
var body UpdateUserParams
if err := c.ShouldBindJSON(&body); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}
c.JSON(200, gin.H{
"id": params.ID,
"name": body.Name,
})
})
package main
import (
"github.com/gin-gonic/gin"
"net/http"
"strconv"
)
type UserIDParams struct {
ID int `uri:"id" binding:"required,gt=0"`
}
type PostIDParams struct {
UserID int `uri:"user_id" binding:"required,gt=0"`
PostID int `uri:"post_id" binding:"required,gt=0"`
}
type FilePathParams struct {
Path string `uri:"path"`
}
func main() {
r := gin.Default()
r.GET("/users/:id", getUser)
r.GET("/users/:user_id/posts/:post_id", getPost)
r.GET("/files/*path", getFile)
r.Run(":8080")
}
func getUser(c *gin.Context) {
var params UserIDParams
if err := c.ShouldBindUri(¶ms); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的用户 ID"})
return
}
c.JSON(http.StatusOK, gin.H{
"id": params.ID,
"name": "User " + strconv.Itoa(params.ID),
})
}
func getPost(c *gin.Context) {
var params PostIDParams
if err := c.ShouldBindUri(¶ms); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的参数"})
return
}
c.JSON(http.StatusOK, gin.H{
"user_id": params.UserID,
"post_id": params.PostID,
"title": "Post Title",
})
}
func getFile(c *gin.Context) {
var params FilePathParams
if err := c.ShouldBindUri(¶ms); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的文件路径"})
return
}
c.JSON(http.StatusOK, gin.H{
"path": params.Path,
"content": "文件内容",
})
}
这一章学习了: