Loading...
Loading...

Go Routing Tutorial

Routing in Go handles HTTP requests by matching URLs to handler functions. This tutorial covers both the standard library and popular third-party routers.

1. Basic Routing

1.1 Standard Library Router

The net/http package provides basic routing capabilities:

package main

import (
    "fmt"
    "net/http"
)

func homeHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, "Home Page")
}

func main() {
    // Simple route handling
    http.HandleFunc("/", homeHandler)
    http.HandleFunc("/about", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprint(w, "About Page")
    })

    // Start server
    http.ListenAndServe(":8080", nil)
}

Key Points:

  • http.HandleFunc: Binds path to handler function
  • Exact matching: "/about" won't match "/about/"
  • No path parameters: Basic routing only

2. Advanced Routing

2.1 Using gorilla/mux

The gorilla/mux router adds powerful routing features:

package main

import (
    "github.com/gorilla/mux"
    "net/http"
)

func main() {
    r := mux.NewRouter()

    // Exact path matching
    r.HandleFunc("/products/{id}", productHandler).Methods("GET")

    // Route with regex validation
    r.HandleFunc("/articles/{category:[a-z]+}", articlesHandler)

    // Subrouter with prefix
    s := r.PathPrefix("/admin").Subrouter()
    s.HandleFunc("/dashboard", adminDashboard)

    http.ListenAndServe(":8080", r)
}

gorilla/mux Features:

  • Path parameters: Capture values from URLs
  • Method matching: Restrict to GET/POST/etc
  • Regex validation: Validate path segments
  • Subrouters: Group related routes

3. RESTful Routing

3.1 Resource-Based Routes

Proper REST APIs use HTTP methods for CRUD operations:

func main() {
    r := mux.NewRouter()

    // Collection routes
    r.HandleFunc("/users", listUsers).Methods("GET")
    r.HandleFunc("/users", createUser).Methods("POST")

    // Item routes
    r.HandleFunc("/users/{id}", getUser).Methods("GET")
    r.HandleFunc("/users/{id}", updateUser).Methods("PUT")
    r.HandleFunc("/users/{id}", deleteUser).Methods("DELETE")

    // Nested resources
    r.HandleFunc("/users/{id}/posts", getUserPosts).Methods("GET")
}

3.2 Route Naming

Name routes for URL generation:

r.HandleFunc("/users/{id}", getUser).
    Methods("GET").
    Name("user")

// Generate URL later
url, _ := r.Get("user").URL("id", "123")
fmt.Println(url.Path) // "/users/123"

4. Middleware in Routing

4.1 Route-Specific Middleware

Apply middleware to specific routes or groups:

func loggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        log.Println(r.Method, r.URL.Path)
        next.ServeHTTP(w, r)
    })
}

func main() {
    r := mux.NewRouter()
    
    // Global middleware
    r.Use(loggingMiddleware)
    
    // Route-specific middleware
    r.Handle("/admin", adminHandler).Middleware(authMiddleware)
    
    // Subrouter with middleware
    api := r.PathPrefix("/api").Subrouter()
    api.Use(jsonMiddleware)
}

4.2 Common Middleware Examples

// CORS middleware
func corsMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Access-Control-Allow-Origin", "*")
        next.ServeHTTP(w, r)
    })
}

// Authentication middleware
func authMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        if !isAuthenticated(r) {
            http.Error(w, "Unauthorized", http.StatusUnauthorized)
            return
        }
        next.ServeHTTP(w, r)
    })
}

5. Performance Considerations

5.1 Router Benchmarks

Different routers have varying performance characteristics:

// Standard library: Fastest but least features
http.HandleFunc("/", handler)

// gorilla/mux: Feature-rich with moderate overhead
r := mux.NewRouter()
r.HandleFunc("/", handler)

// httprouter: High performance with good features
router := httprouter.New()
router.GET("/", handler)

// chi: Lightweight with good performance
r := chi.NewRouter()
r.Get("/", handler)

5.2 Optimization Tips

  • Compile routes once at startup
  • Avoid regex in hot paths when possible
  • Use simple patterns for static routes
  • Benchmark with your specific workload

6. Common Pitfalls

6.1 Trailing Slash Mismatch

Routes with and without trailing slashes are different:

r.HandleFunc("/path", handler1)   // Doesn't match "/path/"
r.HandleFunc("/path/", handler2) // Doesn't match "/path"

// Solution: Handle both explicitly or use StrictSlash(true)
r := mux.NewRouter()
r.StrictSlash(true)
r.HandleFunc("/path", handler) // Now matches both

6.2 Route Conflicts

Ambiguous routes can cause unexpected matches:

// Problematic ordering
r.HandleFunc("/users/{id}", userHandler)
r.HandleFunc("/users/new", newUserHandler) // Never matches

// Solution: Specific routes first
r.HandleFunc("/users/new", newUserHandler)
r.HandleFunc("/users/{id}", userHandler)
0 Interaction
0 Views
Views
0 Likes
×
×
×
🍪 CookieConsent@Ptutorials:~

Welcome to Ptutorials

$ Allow cookies on this site ? (y/n)

top-home