func (r *Router) NotFound(handlers ...Handler) {
	handlers = validateAndWrapHandlers(handlers)
	r.notFound = func(rw http.ResponseWriter, req *http.Request) {
		c := r.m.createContext(rw, req)
		c.handlers = make([]Handler, 0, len(r.m.handlers)+len(handlers))
		c.handlers = append(c.handlers, r.m.handlers...)
		c.handlers = append(c.handlers, handlers...)
		c.run()
	}
}
NotFound configurates http.HandlerFunc which is called when no matching route is
found. If it is not set, http.NotFound is used.
Be sure to set 404 response code in your handler.
package macaron
import (
	"net/http"
	"strings"
	"sync"
)
var (
	_HTTP_METHODS = map[string]bool{
		"GET":     true,
		"POST":    true,
		"PUT":     true,
		"DELETE":  true,
		"PATCH":   true,
		"OPTIONS": true,
		"HEAD":    true,
	}
)
type routeMap struct {
	lock   sync.RWMutex
	routes map[string]map[string]*Leaf
}
func NewRouteMap() *routeMap {
	rm := &routeMap{
		routes: make(map[string]map[string]*Leaf),
	}
	for m := range _HTTP_METHODS {
		rm.routes[m] = make(map[string]*Leaf)
	}
	return rm
}
func (rm *routeMap) getLeaf(method, pattern string) *Leaf {
	rm.lock.RLock()
	defer rm.lock.RUnlock()
	return rm.routes[method][pattern]
}
func (rm *routeMap) add(method, pattern string, leaf *Leaf) {
	rm.lock.Lock()
	defer rm.lock.Unlock()
	rm.routes[method][pattern] = leaf
}
type group struct {
	pattern  string
	handlers []Handler
}
type Router struct {
	m        *Macaron
	autoHead bool
	routers  map[string]*Tree
	*routeMap
	namedRoutes map[string]*Leaf
	groups              []group
	notFound            http.HandlerFunc
	internalServerError func(*Context, error)
	handlerWrapper func(Handler) Handler
}
func NewRouter() *Router {
	return &Router{
		routers:     make(map[string]*Tree),
		routeMap:    NewRouteMap(),
		namedRoutes: make(map[string]*Leaf),
	}
}
func (r *Router) SetAutoHead(v bool) {
	r.autoHead = v
}
type Params map[string]string
type Handle func(http.ResponseWriter, *http.Request, Params)
type Route struct {
	router *Router
	leaf   *Leaf
}
func (r *Route) Name(name string) {
	if len(name) == 0 {
		panic("route name cannot be empty")
	} else if r.router.namedRoutes[name] != nil {
		panic("route with given name already exists: " + name)
	}
	r.router.namedRoutes[name] = r.leaf
}
func (r *Router) handle(method, pattern string, handle Handle) *Route {
	method = strings.ToUpper(method)
	var leaf *Leaf
	if leaf = r.getLeaf(method, pattern); leaf != nil {
		return &Route{r, leaf}
	}
	if !_HTTP_METHODS[method] && method != "*" {
		panic("unknown HTTP method: " + method)
	}
	methods := make(map[string]bool)
	if method == "*" {
		for m := range _HTTP_METHODS {
			methods[m] = true
		}
	} else {
		methods[method] = true
	}
	for m := range methods {
		if t, ok := r.routers[m]; ok {
			leaf = t.Add(pattern, handle)
		} else {
			t := NewTree()
			leaf = t.Add(pattern, handle)
			r.routers[m] = t
		}
		r.add(m, pattern, leaf)
	}
	return &Route{r, leaf}
}
func (r *Router) Handle(method string, pattern string, handlers []Handler) *Route {
	if len(r.groups) > 0 {
		groupPattern := ""
		h := make([]Handler, 0)
		for _, g := range r.groups {
			groupPattern += g.pattern
			h = append(h, g.handlers...)
		}
		pattern = groupPattern + pattern
		h = append(h, handlers...)
		handlers = h
	}
	handlers = validateAndWrapHandlers(handlers, r.handlerWrapper)
	return r.handle(method, pattern, func(resp http.ResponseWriter, req *http.Request, params Params) {
		c := r.m.createContext(resp, req)
		c.params = params
		c.handlers = make([]Handler, 0, len(r.m.handlers)+len(handlers))
		c.handlers = append(c.handlers, r.m.handlers...)
		c.handlers = append(c.handlers, handlers...)
		c.run()
	})
}
func (r *Router) Group(pattern string, fn func(), h ...Handler) {
	r.groups = append(r.groups, group{pattern, h})
	fn()
	r.groups = r.groups[:len(r.groups)-1]
}
func (r *Router) Get(pattern string, h ...Handler) (leaf *Route) {
	leaf = r.Handle("GET", pattern, h)
	if r.autoHead {
		r.Head(pattern, h...)
	}
	return leaf
}
func (r *Router) Patch(pattern string, h ...Handler) *Route {
	return r.Handle("PATCH", pattern, h)
}
func (r *Router) Post(pattern string, h ...Handler) *Route {
	return r.Handle("POST", pattern, h)
}
func (r *Router) Put(pattern string, h ...Handler) *Route {
	return r.Handle("PUT", pattern, h)
}
func (r *Router) Delete(pattern string, h ...Handler) *Route {
	return r.Handle("DELETE", pattern, h)
}
func (r *Router) Options(pattern string, h ...Handler) *Route {
	return r.Handle("OPTIONS", pattern, h)
}
func (r *Router) Head(pattern string, h ...Handler) *Route {
	return r.Handle("HEAD", pattern, h)
}
func (r *Router) Any(pattern string, h ...Handler) *Route {
	return r.Handle("*", pattern, h)
}
func (r *Router) Route(pattern, methods string, h ...Handler) (route *Route) {
	for _, m := range strings.Split(methods, ",") {
		route = r.Handle(strings.TrimSpace(m), pattern, h)
	}
	return route
}
func (r *Router) Combo(pattern string, h ...Handler) *ComboRouter {
	return &ComboRouter{r, pattern, h, map[string]bool{}, nil}
}