路由参数 #
一、参数类型概述 #
Echo支持多种参数类型,满足不同的请求场景。
1.1 参数类型 #
text
┌─────────────────────────────────────────────────────────┐
│ 参数类型 │
├─────────────────────────────────────────────────────────┤
│ │
│ 路径参数 (Path Params) │
│ └── /users/:id → c.Param("id") │
│ │
│ 查询参数 (Query Params) │
│ └── /users?page=1&size=10 → c.QueryParam("page") │
│ │
│ 表单参数 (Form Values) │
│ └── POST body: name=张三 → c.FormValue("name") │
│ │
│ JSON参数 (JSON Body) │
│ └── POST body: {"name":"张三"} → c.Bind(&user) │
│ │
│ 请求头 (Headers) │
│ └── Authorization: Bearer xxx → c.Request().Header │
│ │
│ Cookie │
│ └── session=abc123 → c.Cookie("session") │
│ │
└─────────────────────────────────────────────────────────┘
二、路径参数 #
2.1 基本用法 #
使用 :param 定义路径参数:
go
e.GET("/users/:id", func(c echo.Context) error {
id := c.Param("id")
return c.String(http.StatusOK, "User ID: "+id)
})
测试:
bash
curl http://localhost:8080/users/123
User ID: 123
2.2 多个路径参数 #
go
e.GET("/users/:userId/posts/:postId", func(c echo.Context) error {
userId := c.Param("userId")
postId := c.Param("postId")
return c.JSON(http.StatusOK, map[string]string{
"userId": userId,
"postId": postId,
})
})
测试:
bash
curl http://localhost:8080/users/1/posts/100
{"userId":"1","postId":"100"}
2.3 通配符参数 #
使用 * 匹配任意路径:
go
e.GET("/files/*", func(c echo.Context) error {
path := c.Param("*")
return c.String(http.StatusOK, "File: "+path)
})
测试:
bash
curl http://localhost:8080/files/docs/readme.md
File: docs/readme.md
2.4 参数验证 #
go
e.GET("/users/:id", func(c echo.Context) error {
id := c.Param("id")
if _, err := strconv.Atoi(id); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "ID必须是数字")
}
return c.String(http.StatusOK, "User ID: "+id)
})
三、查询参数 #
3.1 基本用法 #
go
e.GET("/search", func(c echo.Context) error {
q := c.QueryParam("q")
return c.String(http.StatusOK, "Search: "+q)
})
测试:
bash
curl "http://localhost:8080/search?q=echo"
Search: echo
3.2 多个查询参数 #
go
e.GET("/users", func(c echo.Context) error {
page := c.QueryParam("page")
size := c.QueryParam("size")
sort := c.QueryParam("sort")
return c.JSON(http.StatusOK, map[string]string{
"page": page,
"size": size,
"sort": sort,
})
})
测试:
bash
curl "http://localhost:8080/users?page=1&size=10&sort=name"
{"page":"1","size":"10","sort":"name"}
3.3 默认值处理 #
go
e.GET("/users", func(c echo.Context) error {
page := c.QueryParam("page")
if page == "" {
page = "1"
}
size := c.QueryParam("size")
if size == "" {
size = "10"
}
return c.JSON(http.StatusOK, map[string]string{
"page": page,
"size": size,
})
})
3.4 QueryParams获取所有参数 #
go
e.GET("/filter", func(c echo.Context) error {
params := c.QueryParams()
result := make(map[string][]string)
for key, values := range params {
result[key] = values
}
return c.JSON(http.StatusOK, result)
})
测试:
bash
curl "http://localhost:8080/filter?tag=go&tag=echo&status=active"
{"status":["active"],"tag":["go","echo"]}
3.5 绑定查询参数 #
go
type PaginationQuery struct {
Page int `query:"page"`
Size int `query:"size"`
Sort string `query:"sort"`
}
e.GET("/users", func(c echo.Context) error {
q := new(PaginationQuery)
if err := c.Bind(q); err != nil {
return err
}
if q.Page == 0 {
q.Page = 1
}
if q.Size == 0 {
q.Size = 10
}
return c.JSON(http.StatusOK, q)
})
四、表单参数 #
4.1 基本用法 #
go
e.POST("/login", func(c echo.Context) error {
username := c.FormValue("username")
password := c.FormValue("password")
return c.JSON(http.StatusOK, map[string]string{
"username": username,
"status": "success",
})
})
测试:
bash
curl -X POST -d "username=admin&password=123456" http://localhost:8080/login
{"username":"admin","status":"success"}
4.2 多值表单参数 #
go
e.POST("/tags", func(c echo.Context) error {
tags := c.Request().Form["tags"]
return c.JSON(http.StatusOK, map[string][]string{
"tags": tags,
})
})
测试:
bash
curl -X POST -d "tags=go&tags=echo&tags=web" http://localhost:8080/tags
{"tags":["go","echo","web"]}
4.3 绑定表单参数 #
go
type LoginForm struct {
Username string `form:"username"`
Password string `form:"password"`
}
e.POST("/login", func(c echo.Context) error {
form := new(LoginForm)
if err := c.Bind(form); err != nil {
return err
}
return c.JSON(http.StatusOK, form)
})
五、JSON参数 #
5.1 基本用法 #
go
type User struct {
Name string `json:"name"`
Email string `json:"email"`
Age int `json:"age"`
}
e.POST("/users", func(c echo.Context) error {
u := new(User)
if err := c.Bind(u); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
return c.JSON(http.StatusCreated, u)
})
测试:
bash
curl -X POST \
-H "Content-Type: application/json" \
-d '{"name":"张三","email":"zhangsan@example.com","age":25}' \
http://localhost:8080/users
5.2 嵌套JSON #
go
type Address struct {
City string `json:"city"`
Country string `json:"country"`
}
type User struct {
Name string `json:"name"`
Address Address `json:"address"`
}
e.POST("/users", func(c echo.Context) error {
u := new(User)
if err := c.Bind(u); err != nil {
return err
}
return c.JSON(http.StatusCreated, u)
})
测试:
bash
curl -X POST \
-H "Content-Type: application/json" \
-d '{"name":"张三","address":{"city":"北京","country":"中国"}}' \
http://localhost:8080/users
5.3 JSON数组 #
go
e.POST("/users/batch", func(c echo.Context) error {
var users []User
if err := c.Bind(&users); err != nil {
return err
}
return c.JSON(http.StatusCreated, map[string]int{
"count": len(users),
})
})
测试:
bash
curl -X POST \
-H "Content-Type: application/json" \
-d '[{"name":"张三"},{"name":"李四"}]' \
http://localhost:8080/users/batch
六、请求头参数 #
6.1 获取单个请求头 #
go
e.GET("/headers", func(c echo.Context) error {
auth := c.Request().Header.Get("Authorization")
contentType := c.Request().Header.Get("Content-Type")
return c.JSON(http.StatusOK, map[string]string{
"authorization": auth,
"content-type": contentType,
})
})
测试:
bash
curl -H "Authorization: Bearer token123" http://localhost:8080/headers
{"authorization":"Bearer token123","content-type":""}
6.2 获取所有请求头 #
go
e.GET("/headers/all", func(c echo.Context) error {
headers := make(map[string][]string)
for key, values := range c.Request().Header {
headers[key] = values
}
return c.JSON(http.StatusOK, headers)
})
6.3 常用请求头 #
go
e.GET("/info", func(c echo.Context) error {
userAgent := c.Request().UserAgent()
host := c.Request().Host
referer := c.Request().Header.Get("Referer")
return c.JSON(http.StatusOK, map[string]string{
"userAgent": userAgent,
"host": host,
"referer": referer,
})
})
七、Cookie参数 #
7.1 获取Cookie #
go
e.GET("/cookie", func(c echo.Context) error {
cookie, err := c.Cookie("session")
if err != nil {
return c.String(http.StatusOK, "No cookie")
}
return c.String(http.StatusOK, "Session: "+cookie.Value)
})
7.2 设置Cookie #
go
e.GET("/set-cookie", func(c echo.Context) error {
cookie := &http.Cookie{
Name: "session",
Value: "abc123",
Path: "/",
HttpOnly: true,
Secure: true,
MaxAge: 3600,
}
c.SetCookie(cookie)
return c.String(http.StatusOK, "Cookie set")
})
7.3 获取所有Cookie #
go
e.GET("/cookies", func(c echo.Context) error {
cookies := c.Cookies()
result := make(map[string]string)
for _, cookie := range cookies {
result[cookie.Name] = cookie.Value
}
return c.JSON(http.StatusOK, result)
})
八、参数绑定 #
8.1 Bind方法 #
Bind方法自动根据Content-Type绑定数据:
go
type User struct {
Name string `json:"name" form:"name" query:"name"`
Email string `json:"email" form:"email" query:"email"`
}
e.POST("/users", func(c echo.Context) error {
u := new(User)
if err := c.Bind(u); err != nil {
return err
}
return c.JSON(http.StatusCreated, u)
})
8.2 绑定来源优先级 #
text
1. URL路径参数
2. 查询参数
3. 请求体
8.3 指定绑定来源 #
go
type User struct {
Name string `query:"name"`
}
e.GET("/users", func(c echo.Context) error {
u := new(User)
if err := c.Bind(u); err != nil {
return err
}
return c.JSON(http.StatusOK, u)
})
九、参数验证 #
9.1 使用validator #
安装validator:
bash
go get github.com/go-playground/validator/v10
配置验证器:
go
package main
import (
"net/http"
"github.com/go-playground/validator/v10"
"github.com/labstack/echo/v4"
)
type User struct {
Name string `json:"name" validate:"required"`
Email string `json:"email" validate:"required,email"`
Age int `json:"age" validate:"gte=0,lte=130"`
}
type CustomValidator struct {
validator *validator.Validate
}
func (cv *CustomValidator) Validate(i interface{}) error {
return cv.validator.Struct(i)
}
func main() {
e := echo.New()
e.Validator = &CustomValidator{validator: validator.New()}
e.POST("/users", func(c echo.Context) error {
u := new(User)
if err := c.Bind(u); err != nil {
return err
}
if err := c.Validate(u); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
return c.JSON(http.StatusCreated, u)
})
e.Start(":8080")
}
9.2 验证标签 #
| 标签 | 说明 |
|---|---|
required |
必填 |
email |
邮箱格式 |
min=x |
最小值 |
max=x |
最大值 |
gte=x |
大于等于 |
lte=x |
小于等于 |
oneof=x y z |
枚举值 |
url |
URL格式 |
datetime |
日期时间格式 |
9.3 自定义验证 #
go
func (cv *CustomValidator) Validate(i interface{}) error {
cv.validator.RegisterValidation("custom", func(fl validator.FieldLevel) bool {
return fl.Field().String() == "valid"
})
return cv.validator.Struct(i)
}
type Data struct {
Value string `json:"value" validate:"custom"`
}
十、综合示例 #
go
package main
import (
"net/http"
"strconv"
"github.com/go-playground/validator/v10"
"github.com/labstack/echo/v4"
)
type User struct {
ID int `json:"id" param:"id"`
Name string `json:"name" form:"name" query:"name" validate:"required"`
Email string `json:"email" form:"email" query:"email" validate:"required,email"`
Age int `json:"age" form:"age" query:"age" validate:"gte=0,lte=130"`
Password string `json:"password" form:"password" validate:"required,min=6"`
}
type CustomValidator struct {
validator *validator.Validate
}
func (cv *CustomValidator) Validate(i interface{}) error {
return cv.validator.Struct(i)
}
func main() {
e := echo.New()
e.Validator = &CustomValidator{validator: validator.New()}
e.GET("/users/:id", getUser)
e.GET("/users", listUsers)
e.POST("/users", createUser)
e.POST("/login", login)
e.Start(":8080")
}
func getUser(c echo.Context) error {
id := c.Param("id")
if _, err := strconv.Atoi(id); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "ID必须是数字")
}
user := &User{
ID: 1,
Name: "张三",
Email: "zhangsan@example.com",
Age: 25,
}
return c.JSON(http.StatusOK, user)
}
func listUsers(c echo.Context) error {
page := c.QueryParam("page")
size := c.QueryParam("size")
users := []*User{
{ID: 1, Name: "张三", Email: "zhangsan@example.com", Age: 25},
{ID: 2, Name: "李四", Email: "lisi@example.com", Age: 30},
}
return c.JSON(http.StatusOK, map[string]interface{}{
"page": page,
"size": size,
"users": users,
})
}
func createUser(c echo.Context) error {
u := new(User)
if err := c.Bind(u); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
if err := c.Validate(u); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
u.ID = 3
return c.JSON(http.StatusCreated, u)
}
func login(c echo.Context) error {
u := new(User)
if err := c.Bind(u); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
if err := c.Validate(u); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
return c.JSON(http.StatusOK, map[string]string{
"token": "jwt-token-here",
})
}
十一、总结 #
参数获取方法:
| 方法 | 用途 | 示例 |
|---|---|---|
Param() |
路径参数 | c.Param("id") |
QueryParam() |
查询参数 | c.QueryParam("page") |
QueryParams() |
所有查询参数 | c.QueryParams() |
FormValue() |
表单参数 | c.FormValue("name") |
Bind() |
绑定到结构体 | c.Bind(&user) |
Cookie() |
Cookie | c.Cookie("session") |
Header.Get() |
请求头 | c.Request().Header.Get("Auth") |
准备好学习路由分组了吗?让我们进入下一章!
最后更新:2026-03-28