查询参数是 URL 中
?后面的部分,比如/search?q=golang&page=1。Gin 提供了多种方法来获取查询参数。
使用 Query() 获取查询参数:
r.GET("/search", func(c *gin.Context) {
query := c.Query("q")
c.JSON(200, gin.H{"query": query})
})
访问 /search?q=golang,query 的值是 golang。
如果参数不存在,返回空字符串。
DefaultQuery() 可以设置默认值:
r.GET("/search", func(c *gin.Context) {
page := c.DefaultQuery("page", "1")
size := c.DefaultQuery("size", "10")
c.JSON(200, gin.H{
"page": page,
"size": size,
})
})
访问 /search,page 和 size 都是默认值。
访问 /search?page=2&size=20,会使用传入的值。
Query() 返回空字符串时,可能是参数不存在,也可能是值为空。用 GetQuery() 可以区分:
r.GET("/search", func(c *gin.Context) {
query, exists := c.GetQuery("q")
if !exists {
c.JSON(400, gin.H{"error": "缺少查询参数 q"})
return
}
c.JSON(200, gin.H{"query": query})
})
QueryMap() 返回所有查询参数:
r.GET("/search", func(c *gin.Context) {
params := c.QueryMap()
for key, values := range params {
for _, value := range values {
fmt.Printf("%s = %s\n", key, value)
}
}
c.JSON(200, params)
})
URL 中可以有同名参数,比如 ?tags=go&tags=web:
r.GET("/filter", func(c *gin.Context) {
tags := c.QueryArray("tags")
c.JSON(200, gin.H{"tags": tags})
})
访问 /filter?tags=go&tags=web&tags=api,会得到 ["go", "web", "api"]。
查询参数都是字符串,使用时需要转换:
import "strconv"
r.GET("/users", func(c *gin.Context) {
pageStr := c.DefaultQuery("page", "1")
limitStr := c.DefaultQuery("limit", "10")
page, err := strconv.Atoi(pageStr)
if err != nil {
c.JSON(400, gin.H{"error": "无效的页码"})
return
}
limit, err := strconv.Atoi(limitStr)
if err != nil {
c.JSON(400, gin.H{"error": "无效的限制数量"})
return
}
c.JSON(200, gin.H{
"page": page,
"limit": limit,
})
})
r.GET("/posts", func(c *gin.Context) {
page := c.DefaultQuery("page", "1")
pageSize := c.DefaultQuery("page_size", "10")
sortBy := c.DefaultQuery("sort_by", "created_at")
order := c.DefaultQuery("order", "desc")
c.JSON(200, gin.H{
"page": page,
"page_size": pageSize,
"sort_by": sortBy,
"order": order,
"posts": []string{},
})
})
r.GET("/products", func(c *gin.Context) {
keyword := c.Query("keyword")
category := c.Query("category")
minPrice := c.Query("min_price")
maxPrice := c.Query("max_price")
filters := gin.H{}
if keyword != "" {
filters["keyword"] = keyword
}
if category != "" {
filters["category"] = category
}
if minPrice != "" {
filters["min_price"] = minPrice
}
if maxPrice != "" {
filters["max_price"] = maxPrice
}
c.JSON(200, gin.H{
"filters": filters,
"products": []string{},
})
})
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
"strconv"
)
type Pagination struct {
Page int `json:"page"`
PageSize int `json:"page_sizePageSize"`
}
type Filter struct {
Keyword string `json:"keyword"`
Category string `json:"category"`
}
func main() {
r := gin.Default()
r.GET("/posts", listPosts)
r.GET("/products", listProducts)
r.Run(":8080")
}
func listPosts(c *gin.Context) {
pagination, err := parsePagination(c)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
c.JSON(http.StatusOK, gin.H{
"pagination": pagination,
"posts": []string{},
})
}
func listProducts(c *gin.Context) {
pagination, err := parsePagination(c)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
filter := parseFilter(c)
c.JSON(http.StatusOK, gin.H{
"pagination": pagination,
"filter": filter,
"products": []string{},
})
}
func parsePagination(c *gin.Context) (*Pagination, error) {
pageStr := c.DefaultQuery("page", "1")
pageSizeStr := c.DefaultQuery("page_size", "10")
page, err := strconv.Atoi(pageStr)
if err != nil {
return nil, fmt.Errorf("无效的页码")
}
pageSize, err := strconv.Atoi(pageSizeStr)
if err != nil {
return nil, fmt.Errorf("无效的每页数量")
}
if page < 1 {
page = 1
}
if pageSize < 1 || pageSize > 100 {
pageSize = 10
}
return &Pagination{
Page: page,
PageSize: pageSize,
}, nil
}
func parseFilter(c *gin.Context) *Filter {
return &Filter{
Keyword: c.Query("keyword"),
Category: c.Query("category"),
}
}
查询参数中的特殊字符需要 URL 编码:
import "net/url"
r.GET("/search", func(c *gin.Context) {
query := c.Query("q")
encoded := url.QueryEscape(query)
decoded, _ := url.QueryUnescape(encoded)
c.JSON(200, gin.H{
"original": query,
"encoded": encoded,
"decoded": decoded,
})
})
这一章学习了:
Query() 获取查询参数DefaultQuery() 设置默认值GetQuery() 检查参数是否存在QueryArray() 获取数组参数