func (rt *router) start() error {
	rt.trie = trie.New()
	rt.index = map[*Route]int{}
	for i, route := range rt.Routes {
		pathExp, err := escapedPathExp(route.PathExp)
		if err != nil {
			return err
		}
		err = rt.trie.AddRoute(
			strings.ToUpper(route.HttpMethod),  
			pathExp,
			route,
		)
		if err != nil {
			return err
		}
		rt.index[route] = i
	}
	if rt.disableTrieCompression == false {
		rt.trie.Compress()
	}
	return nil
}
This validates the Routes and prepares the Trie data structure.
It must be called once the Routes are defined and before trying to find Routes.
The order matters, if multiple Routes match, the first defined will be used.
package rest
import (
	"errors"
	"github.com/ant0ine/go-json-rest/rest/trie"
	"net/http"
	"net/url"
	"strings"
)
type router struct {
	Routes []*Route
	disableTrieCompression bool
	index                  map[*Route]int
	trie                   *trie.Trie
}
func MakeRouter(routes ...*Route) (App, error) {
	r := &router{
		Routes: routes,
	}
	err := r.start()
	if err != nil {
		return nil, err
	}
	return r, nil
}
func (rt *router) AppFunc() HandlerFunc {
	return func(writer ResponseWriter, request *Request) {
		route, params, pathMatched := rt.findRouteFromURL(request.Method, request.URL)
		if route == nil {
			if pathMatched {
				Error(writer, "Method not allowed", http.StatusMethodNotAllowed)
				return
			}
			NotFound(writer, request)
			return
		}
		request.PathParams = params
		handler := route.Func
		handler(writer, request)
	}
}
func escapedPath(urlObj *url.URL) string {
	parts := strings.SplitN(urlObj.RequestURI(), "?", 2)
	return parts[0]
}
var preEscape = strings.NewReplacer("*", "__SPLAT_PLACEHOLDER__", "#", "__RELAXED_PLACEHOLDER__")
var postEscape = strings.NewReplacer("__SPLAT_PLACEHOLDER__", "*", "__RELAXED_PLACEHOLDER__", "#")
func escapedPathExp(pathExp string) (string, error) {
	if pathExp == "" {
		return "", errors.New("empty PathExp")
	}
	if pathExp[0] != '/' {
		return "", errors.New("PathExp must start with /")
	}
	if strings.Contains(pathExp, "?") {
		return "", errors.New("PathExp must not contain the query string")
	}
	pathExp = preEscape.Replace(pathExp)
	urlObj, err := url.Parse(pathExp)
	if err != nil {
		return "", err
	}
	pathExp = urlObj.RequestURI()
	pathExp = postEscape.Replace(pathExp)
	return pathExp, nil
}