API_CHANGES_V5.md
Comparison between master (v4.15.0) and v5 (v5.0.0-alpha) branches
Generated: 2026-01-01
Echo v5 is maintenance release with major breaking changes
Context is now struct instead of interface and we can add method to it in the future in minor versions.Router interface for possible new routing implementations.log/slog instead.Echo v5 represents a major breaking release with significant architectural changes focused on:
*Context and rename form helpers to FormValue*echotest packageechotest)4.15.0 → 5.0.0-alphav4 (master):
type Context interface {
Request() *http.Request
// ... many methods
}
// Handler signature
func handler(c echo.Context) error
v5:
type Context struct {
// Has unexported fields
}
// Handler signature - NOW USES POINTER!
func handler(c *echo.Context) error
Impact: 🔴 CRITICAL BREAKING CHANGE
echo.Context to *echo.ContextMigration:
// Before (v4)
func MyHandler(c echo.Context) error {
return c.JSON(200, map[string]string{"hello": "world"})
}
// After (v5)
func MyHandler(c *echo.Context) error {
return c.JSON(200, map[string]string{"hello": "world"})
}
v4:
type Echo struct {
Logger Logger // Custom interface with Print, Debug, Info, etc.
}
type Logger interface {
Output() io.Writer
SetOutput(w io.Writer)
Prefix() string
// ... many custom methods
}
// Context returns Logger interface
func (c Context) Logger() Logger
v5:
type Echo struct {
Logger *slog.Logger // Standard library structured logger
}
// Context returns slog.Logger
func (c *Context) Logger() *slog.Logger
func (c *Context) SetLogger(logger *slog.Logger)
Impact: 🔴 BREAKING CHANGE
log/slog packagev4:
type Router struct { ... }
func NewRouter(e *Echo) *Router
func (e *Echo) Router() *Router
v5:
type DefaultRouter struct { ... }
func NewRouter(config RouterConfig) *DefaultRouter
func (e *Echo) Router() Router // Returns interface
Changes:
Router interface introducedDefaultRouter is the concrete implementationNewRouter() now takes RouterConfig instead of *EchoNewConcurrentRouter(r Router) Router for thread-safe routingv4:
func (e *Echo) GET(path string, h HandlerFunc, m ...MiddlewareFunc) *Route
func (e *Echo) Any(path string, h HandlerFunc, m ...MiddlewareFunc) []*Route
func (e *Echo) Routes() []*Route
v5:
func (e *Echo) GET(path string, h HandlerFunc, m ...MiddlewareFunc) RouteInfo
func (e *Echo) Any(path string, h HandlerFunc, m ...MiddlewareFunc) RouteInfo
func (e *Echo) Match(...) Routes // Returns Routes type
func (e *Echo) Router() Router // Returns interface
New Types:
type RouteInfo struct {
Name string
Method string
Path string
Parameters []string
}
type Routes []RouteInfo // Collection with helper methods
Impact: 🔴 BREAKING CHANGE
RouteInfo instead of *RouteRoutes collection type with filtering methodsRoute struct still exists but used differentlyv4:
func (c Context) Response() *Response
type Response struct {
Writer http.ResponseWriter
Status int
Size int64
Committed bool
}
func NewResponse(w http.ResponseWriter, e *Echo) *Response
v5:
func (c *Context) Response() http.ResponseWriter
type Response struct {
http.ResponseWriter // Embedded
Status int
Size int64
Committed bool
}
func NewResponse(w http.ResponseWriter, logger *slog.Logger) *Response
func UnwrapResponse(rw http.ResponseWriter) (*Response, error)
Changes:
http.ResponseWriter instead of *Responsehttp.ResponseWriter*slog.Logger instead of *EchoUnwrapResponse() helper functionv4:
type HTTPError struct {
Internal error
Message interface{} // Can be any type
Code int
}
func NewHTTPError(code int, message ...interface{}) *HTTPError
v5:
type HTTPError struct {
Code int
Message string // Now string only
// Has unexported fields (Internal moved)
}
func NewHTTPError(code int, message string) *HTTPError
func (he HTTPError) Wrap(err error) error // New method
func (he *HTTPError) StatusCode() int // Implements HTTPStatusCoder
Changes:
Message field changed from interface{} to stringNewHTTPError() now takes string instead of ...interface{}HTTPStatusCoder interface and StatusCode() methodWrap(err error) method for error wrappingv4:
type HTTPErrorHandler func(err error, c Context)
func (e *Echo) DefaultHTTPErrorHandler(err error, c Context)
v5:
type HTTPErrorHandler func(c *Context, err error) // Parameters swapped!
func DefaultHTTPErrorHandler(exposeError bool) HTTPErrorHandler // Now a factory
Impact: 🔴 BREAKING CHANGE
(c *Context, err error) instead of (err error, c Context)exposeError bool to control error message exposureThese helpers keep the same generic API but now accept *Context, and the
form helpers are renamed from FormParam* to FormValue*:
// Query Parameters
func QueryParam[T any](c *Context, key string, opts ...any) (T, error)
func QueryParamOr[T any](c *Context, key string, defaultValue T, opts ...any) (T, error)
func QueryParams[T any](c *Context, key string, opts ...any) ([]T, error)
func QueryParamsOr[T any](c *Context, key string, defaultValue []T, opts ...any) ([]T, error)
// Path Parameters
func PathParam[T any](c *Context, paramName string, opts ...any) (T, error)
func PathParamOr[T any](c *Context, paramName string, defaultValue T, opts ...any) (T, error)
// Form Values
func FormValue[T any](c *Context, key string, opts ...any) (T, error)
func FormValueOr[T any](c *Context, key string, defaultValue T, opts ...any) (T, error)
func FormValues[T any](c *Context, key string, opts ...any) ([]T, error)
func FormValuesOr[T any](c *Context, key string, defaultValue []T, opts ...any) ([]T, error)
// Generic Parsing
func ParseValue[T any](value string, opts ...any) (T, error)
func ParseValueOr[T any](value string, defaultValue T, opts ...any) (T, error)
func ParseValues[T any](values []string, opts ...any) ([]T, error)
func ParseValuesOr[T any](values []string, defaultValue []T, opts ...any) ([]T, error)
FormParam* was renamed to FormValue*; the rest keep names but now take *Context.
Supported Types:
Example Usage:
// v5 - Type-safe parameter binding
id, err := echo.PathParam[int](c, "id")
page, err := echo.QueryParamOr[int](c, "page", 1)
tags, err := echo.QueryParams[string](c, "tags")
*Context// Type-safe context value retrieval
func ContextGet[T any](c *Context, key string) (T, error)
func ContextGetOr[T any](c *Context, key string, defaultValue T) (T, error)
// Error types
var ErrNonExistentKey = errors.New("non existent key")
var ErrInvalidKeyType = errors.New("invalid key type")
These helpers existed in v4 with Context and now accept *Context.
Example:
// v5
user, err := echo.ContextGet[*User](c, "user")
count, err := echo.ContextGetOr[int](c, "count", 0)
New structured path parameter handling:
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) string
// Context methods
func (c *Context) PathValues() PathValues
func (c *Context) SetPathValues(pathValues PathValues)
type TimeLayout string
const (
TimeLayoutUnixTime = TimeLayout("UnixTime")
TimeLayoutUnixTimeMilli = TimeLayout("UnixTimeMilli")
TimeLayoutUnixTimeNano = TimeLayout("UnixTimeNano")
)
type TimeOpts struct {
Layout TimeLayout
ParseInLocation *time.Location
ToInLocation *time.Location
}
type 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
}
func (sc StartConfig) Start(ctx context.Context, h http.Handler) error
func (sc StartConfig) StartTLS(ctx context.Context, h http.Handler, certFile, keyFile any) error
Example:
// v5 - More control over server startup
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 {
log.Fatal(err)
}
type Config struct {
// Configuration for Echo (logger, binder, renderer, etc.)
}
func NewWithConfig(config Config) *Echo
This adds a configuration struct for creating an Echo instance without
mutating fields after New().
// New route methods
func (e *Echo) AddRoute(route Route) (RouteInfo, error)
func (e *Echo) Middlewares() []MiddlewareFunc
func (e *Echo) PreMiddlewares() []MiddlewareFunc
type AddRouteError struct{ ... }
// Routes collection with filters
type Routes []RouteInfo
func (r Routes) Clone() Routes
func (r Routes) FilterByMethod(method string) (Routes, error)
func (r Routes) FilterByName(name string) (Routes, error)
func (r Routes) FilterByPath(path string) (Routes, error)
func (r Routes) FindByMethodPath(method string, path string) (RouteInfo, error)
func (r Routes) Reverse(routeName string, pathValues ...any) (string, error)
// RouteInfo operations
func (r RouteInfo) Clone() RouteInfo
func (r RouteInfo) Reverse(pathValues ...any) string
type MiddlewareConfigurator interface {
ToMiddleware() (MiddlewareFunc, error)
}
Allows middleware configs to be converted to middleware without panicking.
// v5 additions
func (c *Context) FileFS(file string, filesystem fs.FS) error
func (c *Context) FormValueOr(name, defaultValue string) string
func (c *Context) InitializeRoute(ri *RouteInfo, pathValues *PathValues)
func (c *Context) ParamOr(name, defaultValue string) string
func (c *Context) QueryParamOr(name, defaultValue string) string
func (c *Context) RouteInfo() RouteInfo
func NewVirtualHostHandler(vhosts map[string]*Echo) *Echo
Creates an Echo instance that routes requests to different Echo instances based on host.
func BindBody(c *Context, target any) error
func BindHeaders(c *Context, target any) error
func BindPathValues(c *Context, target any) error // Renamed from BindPathParams
func BindQueryParams(c *Context, target any) error
Top-level binding functions that work with *Context.
package echotest // import "github.com/labstack/echo/v5/echotest"
func LoadBytes(t *testing.T, name string, opts ...loadBytesOpts) []byte
func TrimNewlineEnd(bytes []byte) []byte
type ContextConfig struct{ ... }
type MultipartForm struct{ ... }
type MultipartFormFile struct{ ... }
Helpers for loading fixtures and constructing test contexts.
// v4 - Removed in v5
const CONNECT = http.MethodConnect // Use http.MethodConnect directly
Reason: Deprecated in v4, use stdlib http.Method* constants instead.
// v5 additions
const (
NotFoundRouteName = "echo_route_not_found_name"
)
v4 exports:
ErrBadRequest
ErrInvalidKeyType
ErrNonExistentKey
v5 exports:
ErrBadRequest // Now backed by unexported httpError type
ErrValidatorNotRegistered // New
ErrInvalidKeyType
ErrNonExistentKey
Reason: v5 centralizes on NewHTTPError(code, message) rather than a broad set
of predefined HTTP error variables.
// v4 - Removed in v5
func GetPath(r *http.Request) string // Use r.URL.Path or r.URL.RawPath
// v4 - Removed in v5
var MethodNotAllowedHandler = func(c Context) error { ... }
var NotFoundHandler = func(c Context) error { ... }
// v4
func FormParam[T any](c Context, key string, opts ...any) (T, error)
func FormParamOr[T any](c Context, key string, defaultValue T, opts ...any) (T, error)
func FormParams[T any](c Context, key string, opts ...any) ([]T, error)
func FormParamsOr[T any](c Context, key string, defaultValue []T, opts ...any) ([]T, error)
// v5
func FormValue[T any](c *Context, key string, opts ...any) (T, error)
func FormValueOr[T any](c *Context, key string, defaultValue T, opts ...any) (T, error)
func FormValues[T any](c *Context, key string, opts ...any) ([]T, error)
func FormValuesOr[T any](c *Context, key string, defaultValue []T, opts ...any) ([]T, error)
Echo struct changes:
// v4 fields removed in v5
type Echo struct {
StdLogger *stdLog.Logger // Removed
Server *http.Server // Removed (use StartConfig)
TLSServer *http.Server // Removed (use StartConfig)
Listener net.Listener // Removed (use StartConfig)
TLSListener net.Listener // Removed (use StartConfig)
AutoTLSManager autocert.Manager // Removed
ListenerNetwork string // Removed
OnAddRouteHandler func(...) // Changed to OnAddRoute
DisableHTTP2 bool // Removed (use StartConfig)
Debug bool // Removed
HideBanner bool // Removed (use StartConfig)
HidePort bool // Removed (use StartConfig)
}
// v5 Echo struct (simplified)
type Echo struct {
Binder Binder
Filesystem fs.FS // NEW
Renderer Renderer
Validator Validator
JSONSerializer JSONSerializer
IPExtractor IPExtractor
OnAddRoute func(route Route) error // Simplified
HTTPErrorHandler HTTPErrorHandler
Logger *slog.Logger // Changed from Logger interface
}
Context interface → struct:
// v4
type Context interface {
// Had: SetResponse(*Response)
Response() *Response
// Had: ParamNames(), SetParamNames(), ParamValues(), SetParamValues()
// These are removed in v5 (use PathValues() instead)
}
// v5
type Context struct {
// Concrete struct with unexported fields
}
func (c *Context) Response() http.ResponseWriter // Changed return type
func (c *Context) PathValues() PathValues // Replaces ParamNames/Values
Types removed:
// v4
type Map map[string]interface{}
Group changes:
// v4
func (g *Group) File(path, file string) // No return value
func (g *Group) Static(pathPrefix, fsRoot string) // No return value
func (g *Group) StaticFS(pathPrefix string, filesystem fs.FS) // No return value
// v5
func (g *Group) File(path, file string, middleware ...MiddlewareFunc) RouteInfo
func (g *Group) Static(pathPrefix, fsRoot string, middleware ...MiddlewareFunc) RouteInfo
func (g *Group) StaticFS(pathPrefix string, filesystem fs.FS, middleware ...MiddlewareFunc) RouteInfo
Now return RouteInfo and accept middleware.
// v4
func PathParamsBinder(c Context) *ValueBinder
func QueryParamsBinder(c Context) *ValueBinder
func FormFieldBinder(c Context) *ValueBinder
// v5
func PathValuesBinder(c *Context) *ValueBinder // Renamed
func QueryParamsBinder(c *Context) *ValueBinder
func FormFieldBinder(c *Context) *ValueBinder
// v4
type Binder interface {
Bind(i interface{}, c Context) error
}
// v5
type Binder interface {
Bind(c *Context, target any) error // Parameters swapped!
}
// v4
func (b *DefaultBinder) Bind(i interface{}, c Context) error
func (b *DefaultBinder) BindBody(c Context, i interface{}) error
func (b *DefaultBinder) BindPathParams(c Context, i interface{}) error
// v5
func (b *DefaultBinder) Bind(c *Context, target any) error // Swapped params
// BindBody, BindPathParams, etc. are now top-level functions
// v4
type JSONSerializer interface {
Serialize(c Context, i interface{}, indent string) error
Deserialize(c Context, i interface{}) error
}
// v5
type JSONSerializer interface {
Serialize(c *Context, target any, indent string) error
Deserialize(c *Context, target any) error
}
// v4
type Renderer interface {
Render(io.Writer, string, interface{}, Context) error
}
// v5
type Renderer interface {
Render(c *Context, w io.Writer, templateName string, data any) error
}
Parameters reordered with Context first.
// v4
func NewBindingError(sourceParam string, values []string, message interface{}, internalError error) error
// v5
func NewBindingError(sourceParam string, values []string, message string, err error) error
Message parameter changed from interface{} to string.
// v5 only
func HandlerName(h HandlerFunc) string
New utility function to get handler function name.
// CORS now accepts optional allow-origins
func CORS(allowOrigins ...string) echo.MiddlewareFunc
// BodyLimit now accepts bytes
func BodyLimit(limitBytes int64) echo.MiddlewareFunc
// DefaultSkipper now uses *echo.Context
func DefaultSkipper(c *echo.Context) bool
// Trailing slash configs renamed/split
func AddTrailingSlashWithConfig(config AddTrailingSlashConfig) echo.MiddlewareFunc
func RemoveTrailingSlashWithConfig(config RemoveTrailingSlashConfig) echo.MiddlewareFunc
type AddTrailingSlashConfig struct{ ... }
type RemoveTrailingSlashConfig struct{ ... }
// Auth + extractor signatures now use *echo.Context and add ExtractorSource
type BasicAuthValidator func(c *echo.Context, user string, password string) (bool, error)
type Extractor func(c *echo.Context) (string, error)
type ExtractorSource string
type KeyAuthValidator func(c *echo.Context, key string, source ExtractorSource) (bool, error)
type KeyAuthErrorHandler func(c *echo.Context, err error) error
// BodyDump handler now includes err
type BodyDumpHandler func(c *echo.Context, reqBody []byte, resBody []byte, err error)
// ValuesExtractor now returns extractor source and CreateExtractors takes a limit
type ValuesExtractor func(c *echo.Context) ([]string, ExtractorSource, error)
func CreateExtractors(lookups string, limit uint) ([]ValuesExtractor, error)
type ValueExtractorError struct{ ... }
// New constants
const KB = 1024
// Rate limiter store now takes a float64 limit
func NewRateLimiterMemoryStore(rateLimit float64) (store *RateLimiterMemoryStore)
var ErrInvalidKey = echo.NewHTTPError(http.StatusUnauthorized, "invalid key")
var ErrKeyMissing = echo.NewHTTPError(http.StatusUnauthorized, "missing key")
var RedirectHTTPSConfig = RedirectConfig{ ... }
var RedirectHTTPSWWWConfig = RedirectConfig{ ... }
var RedirectNonHTTPSWWWConfig = RedirectConfig{ ... }
var RedirectNonWWWConfig = RedirectConfig{ ... }
var RedirectWWWConfig = RedirectConfig{ ... }
// Removed in v5
func Logger() echo.MiddlewareFunc
func LoggerWithConfig(config LoggerConfig) echo.MiddlewareFunc
func Timeout() echo.MiddlewareFunc
func TimeoutWithConfig(config TimeoutConfig) echo.MiddlewareFunc
type ErrKeyAuthMissing struct{ ... }
type CSRFErrorHandler func(err error, c echo.Context) error
type LoggerConfig struct{ ... }
type LogErrorFunc func(c echo.Context, err error, stack []byte) error
type TargetProvider interface{ ... }
type TrailingSlashConfig struct{ ... }
type TimeoutConfig struct{ ... }
Also removed defaults: DefaultBasicAuthConfig, DefaultBodyDumpConfig, DefaultBodyLimitConfig,
DefaultCORSConfig, DefaultDecompressConfig, DefaultGzipConfig, DefaultLoggerConfig,
DefaultRedirectConfig, DefaultRequestIDConfig, DefaultRewriteConfig, DefaultTimeoutConfig,
DefaultTrailingSlashConfig.
type Router struct { ... }
func NewRouter(e *Echo) *Router
func (r *Router) Add(method, path string, h HandlerFunc)
func (r *Router) Find(method, path string, c Context)
func (r *Router) Reverse(name string, params ...interface{}) string
func (r *Router) Routes() []*Route
type Router interface {
Add(routable Route) (RouteInfo, error)
Remove(method string, path string) error
Routes() Routes
Route(c *Context) HandlerFunc
}
type DefaultRouter struct { ... }
func NewRouter(config RouterConfig) *DefaultRouter
func NewConcurrentRouter(r Router) Router // NEW
type RouterConfig struct {
NotFoundHandler HandlerFunc
MethodNotAllowedHandler HandlerFunc
OptionsMethodHandler HandlerFunc
AllowOverwritingRoute bool
UnescapePathParamValues bool
UseEscapedPathForMatching bool
}
Key Changes:
(RouteInfo, error) instead of being voidRemove() methodRoute() method replaces Find()RouterConfig// v4
func (e *Echo) Add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) *Route
// v5
func (e *Echo) Add(method, path string, handler HandlerFunc, middleware ...MiddlewareFunc) RouteInfo
func (e *Echo) AddRoute(route Route) (RouteInfo, error) // NEW
// v4
func (e *Echo) Static(pathPrefix, fsRoot string) *Route
func (e *Echo) StaticFS(pathPrefix string, filesystem fs.FS) *Route
func (e *Echo) File(path, file string, m ...MiddlewareFunc) *Route
func (e *Echo) FileFS(path, file string, filesystem fs.FS, m ...MiddlewareFunc) *Route
// v5
func (e *Echo) Static(pathPrefix, fsRoot string, middleware ...MiddlewareFunc) RouteInfo
func (e *Echo) StaticFS(pathPrefix string, filesystem fs.FS, middleware ...MiddlewareFunc) RouteInfo
func (e *Echo) File(path, file string, middleware ...MiddlewareFunc) RouteInfo
func (e *Echo) FileFS(path, file string, filesystem fs.FS, m ...MiddlewareFunc) RouteInfo
Return type changed from *Route to RouteInfo.
// v4
func (e *Echo) Start(address string) error
func (e *Echo) StartTLS(address string, certFile, keyFile interface{}) error
func (e *Echo) StartAutoTLS(address string) error
func (e *Echo) StartH2CServer(address string, h2s *http2.Server) error
func (e *Echo) StartServer(s *http.Server) error
func (e *Echo) Shutdown(ctx context.Context) error
func (e *Echo) Close() error
func (e *Echo) ListenerAddr() net.Addr
func (e *Echo) TLSListenerAddr() net.Addr
func (e *Echo) DefaultHTTPErrorHandler(err error, c Context)
// v5
func (e *Echo) Start(address string) error // Simplified
func (e *Echo) ServeHTTP(w http.ResponseWriter, r *http.Request)
// Removed: StartTLS, StartAutoTLS, StartH2CServer, StartServer
// Use StartConfig instead for advanced server configuration
// Removed: Shutdown, Close, ListenerAddr, TLSListenerAddr
// Removed: DefaultHTTPErrorHandler (now a top-level factory function)
v5 provides StartConfig type for all advanced server configuration.
// v4
func (e *Echo) Router() *Router
func (e *Echo) Routers() map[string]*Router // For multi-host
func (e *Echo) Routes() []*Route
func (e *Echo) Reverse(name string, params ...interface{}) string
func (e *Echo) URI(handler HandlerFunc, params ...interface{}) string
func (e *Echo) URL(h HandlerFunc, params ...interface{}) string
func (e *Echo) Host(name string, m ...MiddlewareFunc) *Group
// v5
func (e *Echo) Router() Router // Returns interface
// Removed: Routers(), Reverse(), URI(), URL(), Host()
// Use router.Routes() and Routes.Reverse() instead
// v4
func (e *Echo) NewContext(r *http.Request, w http.ResponseWriter) Context
func NewResponse(w http.ResponseWriter, e *Echo) *Response
// v5
func (e *Echo) NewContext(r *http.Request, w http.ResponseWriter) *Context
func NewContext(r *http.Request, w http.ResponseWriter, opts ...any) *Context // Standalone
func NewResponse(w http.ResponseWriter, logger *slog.Logger) *Response
If you are using Linux you can migrate easier parts like that:
find . -type f -name "*.go" -exec sed -i 's/ echo.Context/ *echo.Context/g' {} +
find . -type f -name "*.go" -exec sed -i 's/echo\/v4/echo\/v5/g' {} +
or in your favorite IDE
Replace all:
echo.Context -> *echo.Contextecho/v4 -> echo/v5// Before
func MyHandler(c echo.Context) error { ... }
// After
func MyHandler(c *echo.Context) error { ... }
// Before
e.Logger.Info("Server started")
c.Logger().Error("Something went wrong")
// After
e.Logger.Info("Server started")
c.Logger().Error("Something went wrong") // Same API, different logger
// Before
idStr := c.Param("id")
id, err := strconv.Atoi(idStr)
// After
id, err := echo.PathParam[int](c, "id")
// Before
e.HTTPErrorHandler = func(err error, c echo.Context) {
// handle error
}
// After
e.HTTPErrorHandler = func(c *echo.Context, err error) { // Swapped!
// handle error
}
// Or use factory
e.HTTPErrorHandler = echo.DefaultHTTPErrorHandler(true) // exposeError=true
// Before
e.Start(":8080")
e.StartTLS(":443", "cert.pem", "key.pem")
// After
// Simple
e.Start(":8080")
// Advanced with graceful shutdown
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
sc := echo.StartConfig{Address: ":8080"}
sc.Start(ctx, e)
// Before
routes := e.Routes()
for _, r := range routes {
fmt.Println(r.Method, r.Path)
}
// After
routes := e.Router().Routes()
for _, r := range routes {
fmt.Println(r.Method, r.Path)
}
// Before
return echo.NewHTTPError(400, "invalid request", someDetail)
// After
return echo.NewHTTPError(400, "invalid request")
// Before
type MyBinder struct{}
func (b *MyBinder) Bind(i interface{}, c echo.Context) error { ... }
// After
type MyBinder struct{}
func (b *MyBinder) Bind(c *echo.Context, target any) error { ... } // Swapped!
// Before
names := c.ParamNames()
values := c.ParamValues()
// After
pathValues := c.PathValues()
for _, pv := range pathValues {
fmt.Println(pv.Name, pv.Value)
}
// Before
resp := c.Response()
resp.Header().Set("X-Custom", "value")
// After
c.Response().Header().Set("X-Custom", "value") // Returns http.ResponseWriter
// To get *echo.Response
resp, err := echo.UnwrapResponse(c.Response())
go.mod)go.mod)Generated by comparing go doc output from master (v4.15.0) and v5 (v5.0.0-alpha) branches