func (s *ServeMux) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
	ex := s.executionPool.Get()
	s.getAll(req, ex)
	ctx := context.WithValue(req.Context(), executionKey, ex)
	req = req.WithContext(ctx)
	f := getNextMiddleware(ex.middleware, ex.handler)
	f(rw, req)
	s.executionPool.Put(ex)
}
ServeHTTP dispatches the request to the handler whose pattern most closely matches the request URL.
package powermux
import (
	"bytes"
	"context"
	"net/http"
	"strings"
)
type ServeMux struct {
	baseRoute     *Route
	hostRoutes    map[string]*Route
	executionPool *executionPool
}
type ctxKey string
var (
	executionKey = ctxKey("ex")
)
func getRequestExecution(req *http.Request) *routeExecution {
	ex := req.Context().Value(executionKey).(*routeExecution)
	return ex
}
func PathParam(req *http.Request, name string) (value string) {
	ex := getRequestExecution(req)
	return ex.params[name]
}
func PathParams(req *http.Request) (params map[string]string) {
	ex := getRequestExecution(req)
	params = make(map[string]string)
	for k, v := range ex.params {
		params[k] = v
	}
	return
}
func RequestPath(req *http.Request) (value string) {
	ex := getRequestExecution(req)
	return ex.pattern
}
func NewServeMux() *ServeMux {
	s := &ServeMux{
		baseRoute:     newRoute(),
		hostRoutes:    make(map[string]*Route),
		executionPool: newExecutionPool(),
	}
	s.NotFound(http.NotFoundHandler())
	return s
}
func (s *ServeMux) getAll(r *http.Request, ex *routeExecution) {
	path := r.URL.EscapedPath()
	if path != "/" && strings.HasSuffix(path, "/") {
		r.URL.Path = strings.TrimRight(path, "/")
		ex.handler = http.RedirectHandler(r.URL.RequestURI(), http.StatusPermanentRedirect)
		ex.pattern = r.URL.EscapedPath()
		return
	}
	if route, ok := s.hostRoutes[r.URL.Host]; ok {
		route.execute(ex, r.Method, path)
	} else {
		s.baseRoute.execute(ex, r.Method, path)
	}
	if ex.handler == nil {
		ex.handler = ex.notFound
	}
	return
}