定位
Echo 是 Go 的 HTTP 框架,和 Gin 定位最接近但 API 设计更统一。核心特点是中间件接口规范、参数绑定和校验做得整齐。
选它而不是 Gin 的理由通常有两个:想要更严格的参数校验,或者受不了 Gin 的 interface{} 绑定。
安装
go mod init example.com/echo-demo
go get github.com/labstack/echo/v4
最小可运行示例
package main
import (
"net/http"
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New()
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello")
})
e.GET("/users/:id", func(c echo.Context) error {
id := c.Param("id")
return c.JSON(http.StatusOK, map[string]string{"id": id})
})
e.Logger.Fatal(e.Start(":8080"))
}
核心概念
1. Context 贯穿请求
echo.Context 同时承载请求、响应、路径参数、查询参数、表单和自定义数据(c.Set / c.Get)。所有 handler 都接收它,中间件也接收它。
2. 参数绑定与校验一体
这是 Echo 比 Gin 顺手的地方——绑定和校验是同一步:
type CreateUser struct {
Name string `json:"name" validate:"required,min=2"`
Email string `json:"email" validate:"required,email"`
}
e.POST("/users", func(c echo.Context) error {
u := new(CreateUser)
if err := c.Bind(u); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
if err := c.Validate(u); err != nil {
return err
}
return c.JSON(http.StatusCreated, u)
})
校验规则来自 go-playground/validator,和 Gin 用的是同一个库,但 Echo 把「绑定后自动校验」做成了标准流程。
3. 分组路由
api := e.Group("/api")
api.Use(middleware.JWT([]byte("secret"))) // 只作用于 /api 下
v1 := api.Group("/v1")
v1.GET("/users", listUsers)
4. 中间件返回 error
Echo 的中间件签名是 func(next echo.HandlerFunc) echo.HandlerFunc,返回 error。错误会走统一的自定义错误处理器:
e.HTTPErrorHandler = func(err error, c echo.Context) {
if he, ok := err.(*echo.HTTPError); ok {
c.JSON(he.Code, map[string]string{"error": fmt.Sprint(he.Message)})
return
}
c.JSON(500, map[string]string{"error": "internal error"})
}
常见坑
① :id 和 * 的区别
/users/:id 匹配单段;/files/* 匹配剩余全部路径。别混用,也不要在同一层同时定义静态和参数路由(/users/me 和 /users/:id 冲突)。
② Bind 不区分 Content-Type
c.Bind() 会根据请求头自动选择 JSON / form / XML。如果客户端发的 Content-Type 不对,会绑定成空结构体而不报错。需要严格时用 c.BindJSON() 之类的方法。
③ 忘记自定义 HTTPErrorHandler
默认错误响应是 {"message":"Not Found"},格式和你的 API 不一致。项目一开始就该设置。
什么时候选它
- 需要严谨的入参校验
- 团队喜欢显式错误处理(handler 返回 error 而不是自己写响应)
- 项目规模中等,不需要微服务治理
不选它的场景:需要最广的第三方中间件生态(那时选 Gin),或者追求极致性能(那时选 Fiber)。