func (e *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	switch r.Method {
	case http.MethodGet:
		e.serve(w, r, e.getRoutes)
	case http.MethodPost:
		e.serve(w, r, e.postRoutes)
	case http.MethodPut:
		e.serve(w, r, e.putRoutes)
	case http.MethodPatch:
		e.serve(w, r, e.patchRoutes)
	case http.MethodDelete:
		e.serve(w, r, e.deleteRoutes)
	case http.MethodHead:
		e.serve(w, r, e.headRoutes)
	case http.MethodOptions:
		e.serve(w, r, e.optionsRoutes)
	}
}
ServeHTTP implements the http.Handler interface.
package goweb
import (
	"context"
	"fmt"
	"net/http"
	"regexp"
)
type Engine struct {
	server        *http.Server
	getRoutes     []*route
	putRoutes     []*route
	postRoutes    []*route
	patchRoutes   []*route
	deleteRoutes  []*route
	headRoutes    []*route
	optionsRoutes []*route
	notFoundHandler Handler
	loggers []Logger
}
var paramNameRegExp = regexp.MustCompile(`{([a-zA-Z0-9-]+):?(.*?)}`)
func (e *Engine) registerRoute(method string, path string, handler Handler) {
	rt := getRouteFromPath(path)
	rt.handler = handler
	rt.method = method
	switch method {
	case http.MethodGet:
		e.getRoutes = append(e.getRoutes, rt)
	case http.MethodPut:
		e.putRoutes = append(e.putRoutes, rt)
	case http.MethodPatch:
		e.patchRoutes = append(e.patchRoutes, rt)
	case http.MethodPost:
		e.postRoutes = append(e.postRoutes, rt)
	case http.MethodDelete:
		e.deleteRoutes = append(e.deleteRoutes, rt)
	case http.MethodHead:
		e.headRoutes = append(e.headRoutes, rt)
	case http.MethodOptions:
		e.optionsRoutes = append(e.optionsRoutes, rt)
	}
}
func getRouteFromPath(path string) *route {
	rt := new(route)
	if path[0] != '/' {
		panic("path '" + path + "' does not start with '/'")
	}
	pathRegExpStr := "^" + path + "$"
	matches := paramNameRegExp.FindAllStringSubmatch(path, -1)
	for _, match := range matches {
		if match[2] == "" {
			match[2] = `[^\/]*`
		}
		rt.paramNames = append(rt.paramNames, match[1])
		paramInfoRegExp := regexp.MustCompile(fmt.Sprintf("{%s:?(.*?)}", match[1]))
		pathRegExpStr = paramInfoRegExp.ReplaceAllString(pathRegExpStr, "("+match[2]+")")
	}
	rt.regexp = regexp.MustCompile(pathRegExpStr)
	return rt
}
func (e *Engine) GET(path string, handler Handler) {
	e.registerRoute(http.MethodGet, path, handler)
}
func (e *Engine) PUT(path string, handler Handler) {
	e.registerRoute(http.MethodPut, path, handler)
}
func (e *Engine) POST(path string, handler Handler) {
	e.registerRoute(http.MethodPost, path, handler)
}
func (e *Engine) PATCH(path string, handler Handler) {
	e.registerRoute(http.MethodPatch, path, handler)
}
func (e *Engine) DELETE(path string, handler Handler) {
	e.registerRoute(http.MethodDelete, path, handler)
}
func (e *Engine) HEAD(path string, handler Handler) {
	e.registerRoute(http.MethodHead, path, handler)
}
func (e *Engine) OPTIONS(path string, handler Handler) {
	e.registerRoute(http.MethodOptions, path, handler)
}
func (e *Engine) Middleware(middleware ...Handler) *Middleware {
	return &Middleware{
		chain:  middleware,
		engine: e,
	}
}
func (e *Engine) NotFound(handler Handler) {
	e.notFoundHandler = handler
}