Basic Go HTTP router I know Gorilla and others have packages that accomplish this, but I'm trying to learn Go by making stuff. In the router below, the first route / is for all http methods, the second route /hello is only for GET, and the third route hello/:name has one parameter for all HTTP methods.

func main() {
    http.HandleFunc("/", route)
    http.ListenAndServe(":8080", nil)
}

func match(re string, route string) bool {
    match, err := regexp.MatchString(re, route)
    if err != nil {
        return false
    }

    return match
}

func route(w http.ResponseWriter, r *http.Request) {
    route := r.URL.Path
    switch {
    case route == "/":
        home(w, r)
    case route == "/hello" &amp;&amp; r.Method == "GET":
        hello(w, r)
    case match("^/hello/([^/]+)$", route) == true:
        var re = regexp.MustCompile("^/hello/([^/]+)$")
        match := re.FindStringSubmatch(route)

        helloName(w, r, match[1])
    default:
        notFound(w, r)
    }
}

// func home, hello, helloName, and notFound


How can I make this more efficient? Is it reliable?
Instead of case x == true you can use boolean expressions directly,
and write simply:

case x:


The same regex is written twice here.
What's worse is that the pattern matching is also evaluated twice:


case match("^/hello/([^/]+)$", route) == true:
    var re = regexp.MustCompile("^/hello/([^/]+)$")



I'm not sure if there's an elegant solution for this situation in Go.
But at the minimum you could move the regex pattern into a variable to avoid typing it twice.

Another alternative is to create a matcher structure,
with a match function that will not only match a pattern and return a boolean,
but at the same time also store the sub-string you want to extract.

type matcher struct {
    value string
}

func (m *matcher) match(pattern string, route string) bool {
    var re = regexp.MustCompile(pattern)
    matches := re.FindStringSubmatch(route)
    if len(matches) &lt; 2 {
        return false
    }

    m.value = matches[1]

    return true
}


With the help of this, you could rewrite the route function as:

func route(w http.ResponseWriter, r *http.Request) {
    route := r.URL.Path
    m := &amp;matcher{}
    switch {
    case route == "/":
        home(w, r)
    case route == "/hello" &amp;&amp; r.Method == "GET":
        hello(w, r)
    case m.match("^/hello/([^/]+)$", route):
        helloName(w, r, m.value)
    default:
        notFound(w, r)
    }
}