Echo
Echo is a high performance, extensible, minimalist Go web framework built on the standard
net/httplibrary. Echo adds a fast radix-tree router, request binding with pluggable validator, a deep middleware ecosystem, centralized error handling, and template rendering on top of the standard library.
Import path: github.com/labstack/echo/v5
Go version: 1.25+
Handler signature: func(c *echo.Context) error
Context
Context is a concrete struct passed by pointer to all handlers.
type Context struct { ... }
// Handlers receive *echo.Context
func handler(c *echo.Context) error { ... }Context methods
/* Detailed source-code truncated for AI context efficiency. */Context store (type-safe)
c.Set("user", user)
val, err := echo.ContextGet[*User](c, "user")
count, err := echo.ContextGetOr[int](c, "count", 0)Echo struct
type Echo struct {
Binder Binder
Filesystem fs.FS
Renderer Renderer
Validator Validator
JSONSerializer JSONSerializer
IPExtractor IPExtractor
OnAddRoute func(route Route) error
HTTPErrorHandler HTTPErrorHandler
Logger *slog.Logger
}Constructor: echo.New() *Echo or echo.NewWithConfig(config Config) *Echo
Echo methods
Routing
e.GET(path string, h HandlerFunc, m ...MiddlewareFunc) RouteInfo
e.POST(path string, h HandlerFunc, m ...MiddlewareFunc) RouteInfo
e.PUT(path string, h HandlerFunc, m ...MiddlewareFunc) RouteInfo
e.DELETE(path string, h HandlerFunc, m ...MiddlewareFunc) RouteInfo
e.PATCH(path string, h HandlerFunc, m ...MiddlewareFunc) RouteInfo
e.HEAD(path string, h HandlerFunc, m ...MiddlewareFunc) RouteInfo
e.OPTIONS(path string, h HandlerFunc, m ...MiddlewareFunc) RouteInfo
e.ANY(path string, h HandlerFunc, m ...MiddlewareFunc) RouteInfo
e.Match(methods []string, path string, handler HandlerFunc, middleware ...MiddlewareFunc) Routes
e.RouteNotFound(path string, h HandlerFunc, m ...MiddlewareFunc) RouteInfo
e.AddRoute(route Route) (RouteInfo, error)Middleware
e.Use(middleware ...MiddlewareFunc)
e.Pre(middleware ...MiddlewareFunc)
e.Middlewares() []MiddlewareFunc
e.PreMiddlewares() []MiddlewareFuncGroups
e.Group(prefix string, m ...MiddlewareFunc) *GroupStatic files
e.Static(pathPrefix, fsRoot string, m ...MiddlewareFunc) RouteInfo
e.StaticFS(pathPrefix string, filesystem fs.FS, m ...MiddlewareFunc) RouteInfo
e.File(path, file string, m ...MiddlewareFunc) RouteInfo
e.FileFS(file string, filesystem fs.FS, m ...MiddlewareFunc) RouteInfoServer
e.Start(address string) error
e.StartTLS(address string, certFile, keyFile any) errortype StartConfig struct {
Address string
HideBanner bool
HidePort bool
CertFilesystem fs.FS
TLSConfig *tls.Config
ListenerNetwork string
ListenerAddrFunc func(addr net.Addr)
GracefulTimeout time.Duration
OnShutdownError func(err error)
BeforeServeFunc func(s *http.Server) error
}
// StartConfig.Start and StartConfig.StartTLS for graceful shutdown
sc := echo.StartConfig{Address: ":8080", GracefulTimeout: 10 * time.Second}
sc.Start(ctx, e)Error handling
// HTTPError with string message
err := echo.NewHTTPError(http.StatusBadRequest, "invalid input")
// Custom error handler (params: context pointer, then error)
e.HTTPErrorHandler = func(c *echo.Context, err error) {
// custom error handling
}
// Default error handler factory (exposeError bool)
e.HTTPErrorHandler = echo.DefaultHTTPErrorHandler(true)echo.ErrBadRequest
echo.ErrValidatorNotRegistered
echo.ErrInvalidKeyType
echo.ErrNonExistentKeyLogging
Echo uses the standard library log/slog package.
e.Logger = slog.Default()
c.Logger().Info("message", "key", "value")
// Custom logger
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
e.Logger = loggerRouter
// Router interface with DefaultRouter implementation
func NewRouter(config RouterConfig) *DefaultRouter
func (e *Echo) Router() Router
// Thread-safe routing
func NewConcurrentRouter(r Router) RouterRouteInfo
type RouteInfo struct {
Name string
Method string
Path string
Parameters []string
}
// Routes type with filtering methods
type Routes []RouteInfo
// Methods: FilterByMethod, FilterByName, FilterByPath, FindByMethodPath, ReversePathValues
type PathValue struct {
Name string
Value string
}
type PathValues []PathValue
func (p PathValues) Get(name string) (string, bool)
func (p PathValues) GetOr(name string, defaultValue string) stringGeneric helper functions
echo.PathParam[T](c *Context, name string, opts ...any) (T, error)
echo.PathParamOr[T](c *Context, name string, defaultValue T, opts ...any) (T, error)
echo.QueryParam[T](c *Context, key string, opts ...any) (T, error)
echo.QueryParamOr[T](c *Context, key string, defaultValue T, opts ...any) (T, error)
echo.QueryParams[T](c *Context, key string, opts ...any) ([]T, error)
echo.QueryParamsOr[T](c *Context, key string, defaultValue []T, opts ...any) ([]T, error)
echo.FormValue[T](c *Context, key string, opts ...any) (T, error)
echo.FormValueOr[T](c *Context, key string, defaultValue T, opts ...any) (T, error)
echo.FormValues[T](c *Context, key string, opts ...any) ([]T, error)
echo.FormValuesOr[T](c *Context, key string, defaultValue []T, opts ...any) ([]T, error)
echo.ParseValue[T](value string, opts ...any) (T, error)
echo.ParseValueOr[T](value string, defaultValue T, opts ...any) (T, error)
echo.ParseValues[T](values []string, opts ...any) ([]T, error)
echo.ParseValuesOr[T](values []string, defaultValue []T, opts ...any) ([]T, error)
echo.ContextGet[T](c *Context, key string) (T, error)
echo.ContextGetOr[T](c *Context, key string, defaultValue T) (T, error)Supported generic types: bool, string, int/int8/int16/int32/int64, uint/uint8/uint16/uint32/uint64, float32/float64, time.Time, time.Duration, BindUnmarshaler, encoding.TextUnmarshaler, json.Unmarshaler
Binding functions
echo.BindBody(c *Context, target any) error
echo.BindHeaders(c *Context, target any) error
echo.BindPathValues(c *Context, target any) error
echo.BindQueryParams(c *Context, target any) errorBinder helpers
echo.PathValuesBinder(c *Context) *ValueBinder
echo.QueryParamsBinder(c *Context) *ValueBinder
echo.FormFieldBinder(c *Context) *ValueBinderGroup methods
g.Use(m ...MiddlewareFunc)
g.Group(prefix string, m ...MiddlewareFunc) *Group
g.GET(path string, h HandlerFunc, m ...MiddlewareFunc) RouteInfo
g.POST(path string, h HandlerFunc, m ...MiddlewareFunc) RouteInfo
g.PUT(path string, h HandlerFunc, m ...MiddlewareFunc) RouteInfo
g.DELETE(path string, h HandlerFunc, m ...MiddlewareFunc) RouteInfo
g.PATCH(path string, h HandlerFunc, m ...MiddlewareFunc) RouteInfo
g.ANY(path string, h HandlerFunc, m ...MiddlewareFunc) RouteInfo
g.Match(methods []string, path string, handler HandlerFunc, middleware ...MiddlewareFunc) Routes
g.Static(pathPrefix, fsRoot string, m ...MiddlewareFunc) RouteInfo
g.StaticFS(pathPrefix string, filesystem fs.FS, m ...MiddlewareFunc) RouteInfo
g.File(path, file string, m ...MiddlewareFunc) RouteInfo
g.FileFS(file string, filesystem fs.FS, m ...MiddlewareFunc) RouteInfoBuilt-in middleware
| Middleware | Description |
|---|---|
| BasicAuth | HTTP basic authentication |
| BodyDump | Dumps request and response bodies |
| BodyLimit | Limits request body size |
| Compress | Gzip response compression |
| ContextTimeout | Request context timeout |
| CORS | Cross-origin resource sharing |
| CSRF | Cross-site request forgery protection |
| Decompress | Gzip request decompression |
| KeyAuth | Key-based authentication |
| MethodOverride | HTTP method override |
| Proxy | Reverse proxy |
| RateLimiter | Rate limiting |
| Recover | Panic recovery |
| Redirect | HTTP redirect |
| RequestID | Request ID header |
| RequestLogger | Structured request logging |
| Rewrite | URL rewriting |
| Secure | Security headers |
| Slash | Trailing slash handling |
| Static | Static file serving |
Wrapping stdlib handlers
echo.WrapHandler(h http.Handler) HandlerFunc
echo.WrapMiddleware(m func(http.Handler) http.Handler) MiddlewareFuncVirtual host
echo.NewVirtualHostHandler(vhosts map[string]*Echo) *Echoechotest package
import "github.com/labstack/echo/v5/echotest"
echotest.LoadBytes(t *testing.T, name string, opts ...loadBytesOpts) []byte
echotest.TrimNewlineEnd(bytes []byte) []byte
echotest.ContextConfig{...}
echotest.MultipartForm{...}
echotest.MultipartFormFile{...}Complete server example
package main
import (
"context"
"log/slog"
"net/http"
"os"
"os/signal"
"syscall"
"time"
"github.com/labstack/echo/v5"
"github.com/labstack/echo/v5/middleware"
)
func main() {
e := echo.New()
e.Use(middleware.RequestLogger())
e.Use(middleware.Recover())
e.GET("/", func(c *echo.Context) error {
return c.String(http.StatusOK, "Hello, World!")
})
e.GET("/users/:id", func(c *echo.Context) error {
id, err := echo.PathParam[int](c, "id")
if err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "invalid user id")
}
return c.JSON(http.StatusOK, map[string]int{"id": id})
})
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()
sc := echo.StartConfig{
Address: ":8080",
GracefulTimeout: 10 * time.Second,
}
if err := sc.Start(ctx, e); err != nil {
slog.Error("server error", "error", err)
}
}